C# LINQ,选择多个可能的结果

C# LINQ,选择多个可能的结果,c#,linq,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 No

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

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]
  }
}
enum级联{
满满的,
独特的,
正确的,
左边
}
课堂笔记{
int Id{get;set;}
级联{get;set;}
//还有很多其他的数据。
}
var list1=新列表{
新注释{
Id=1,
瀑布,全部,
//资料
},
新注释{
Id=2,
对,
//资料
}
};
var list2=新列表{
新注释{
Id=1,
瀑布,左边,
//资料
}
};
var list3=新列表{
新注释{
Id=1,
独特的,
//与列表1类似的数据。注[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. 
  }
}
Composite(此IList注释){
返回新列表{
notes.SelectMany(g=>g).Where(g=>g.Cascade==Cascade.All).ToList()
//问题是。。。
.SelectMany(g=>g)。其中(g=>g.Cascade==Cascade.Right)
.Select(//我想做一个_LastOrDefault)
//继续进行其他级联。
}
}
这就是我迷路的地方。我需要执行多个
SelectMany
语句,但我不知道如何执行。但这是预期的行为

Cascade.Full
无论发生什么情况,
注释
都将出现在最终收藏中

Cascade.Unique
注释
将在最终集合中出现一次,忽略任何重复项

Cascade.Left
注释
将在最终集合中,第一个实例将取代后续实例。(因此,注释1、2、3是相同的。注释1被推过)

Cascade.Right

注释
将在最终集合中,最后一个实例替换重复项。(所以注释1、2、3是相同的。注释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;
    } 
}
公共静态IEnumerable ApplyCascades(此IEnumerable注释)
{
var uniques=new HashSet();
注意rightToYield=null;
foreach(注释中的变量n)
{
bool=false;
如果(n.Cascade==Cascade.All)收益率返回n;
if(n.Cascade==Cascade.Left&&!Left)
{
收益率n;
左=真;
}
如果(n.Cascade==Cascade.Right)
{
rightToYield=n;
}
如果(n.Cascade==Cascade.Unique&!uniques.Contains(n))
{
收益率n;
添加(n);
} 
}
如果(rightoyield!=null)收益返回rightoyield;
} 
}
此方法允许实现如下原始扩展方法:

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

    }
列表组合(IList注释)
{
var result=来自notes中的列表
来自list.ApplyCascades()中的注释
选择注释;
返回result.ToList();
}

我发现,当LINQ方式不是很明显时,用“长”方式编写代码通常很有帮助。通过这样做,您可以对所有细节进行排序,并得到一个有效的解决方案。然后LINQ版本变得更容易推理。是否有必要保留注释的顺序,或者您只是在寻找结果列表,而不管顺序如何?顺序并不重要,只是在最终编译中是否存在正确的注释。而且您没有奇怪的边缘情况?比如1,Unique/1,Right(哪一个赢了?反过来也是一样,1,Left/1,Unique?那么1,Left/1,Right呢?),这比使用linq语句解决这个问题要好得多。但是我认为您需要
if(n.Cascade==Cascade.Unique&&!uniques.Add(n))
instead@Magnus谢谢,修复了(需要
将注释添加到HashSet中)谢谢,这已经足够好了。但是,我很失望,它不能在一个LINQ查询中完成。