LINQ,SelectMany有多种可能的结果

时间:2011-05-11 18:08:21

标签: c# linq

我有一种情况,我有必须合并的对象列表。列表中的每个对象都有一个属性,用于解释在合并中应该如何处理 的方式。所以假设以下......

enum Cascade {
  Full,
  Unique,
  Right,
  Left
}

class Note {
  int Id { get; set; }
  Cascade Cascade { get; set; }
  // lots of other data.
}

var list1 = new List<Note>{
 new Note {
   Id = 1,
   Cascade.Full,
   // data
 },
 new Note {
   Id = 2,
   Cascade.Right,
   // data
 }
};
var list2 = new List<Note>{
  new Note {
   Id = 1,
   Cascade.Left,
   // data
  }
};
var list3 = new List<Note>{
  new Note {
    Id = 1,
    Cascade.Unique,
    // data similar to list1.Note[0]
  }
}

那么,我会有一个方法......

Composite(this IList<IList<Note>> notes){
  return new List<Note> {
      notes.SelectMany(g => g).Where(g => g.Cascade == Cascade.All).ToList()
      // Here is the problem... 
      .SelectMany(g => g).Where(g => g.Cascade == Cascade.Right)
      .Select( // I want to do a _LastOrDefault_ )
      // continuing for the other cascades. 
  }
}

这是我迷路的地方。我需要做多个SelectMany语句,但我不知道如何做。但这是预期的行为

Cascade.Full

Note无论如何都将在最终收藏中。

Cascade.Unique

Note将在最终集合中一次,忽略任何重复。

Cascade.Left

Note将位于最终集合中,第一个实例将取代后续实例。 (那么,注释1,2,3是相同的。注1被推过)

Cascade.Right

Note将位于最终集合中,最后实例将取代重复项。 (因此,注释1,2,3是相同的。注3被推低)

1 个答案:

答案 0 :(得分:3)

我认为你应该在较小的部分分解问题。例如,您可以在单独的扩展方法中为单个列表实现级联规则。这是我对此未经测试的看法:

public static IEnumerable<Note> ApplyCascades(this IEnumerable<Note> notes)
    {
        var uniques = new HashSet<Note>();
        Note rightToYield = null;
        foreach (var n in notes)
        {
            bool leftYielded = false;

            if (n.Cascade == Cascade.All) yield return n;
            if (n.Cascade == Cascade.Left && !leftYielded)
            {
                yield return n;
                leftYielded = true;
            }
            if (n.Cascade == Cascade.Right)
            {
                rightToYield = n;
            }
            if (n.Cascade == Cascade.Unique && !uniques.Contains(n))
            {
                yield return n;
                uniques.Add(n);
            } 
        }

        if (rightToYield != null) yield return rightToYield;
    } 
}

此方法允许实现原始扩展方法,如下所示:

    List<Note> Composite(IList<IList<Note>> notes)
    {
        var result = from list in notes
                     from note in list.ApplyCascades()
                     select note;
        return result.ToList();

    }