C# linq查询以查找列表项的不同组合,每次使用2个c

C# linq查询以查找列表项的不同组合,每次使用2个c,c#,linq,combinations,C#,Linq,Combinations,时间表是考试的清单 我怎样才能让com变得清晰,无论它包含的考试顺序如何。我认为它现在正在进行置换,我只需要不同的组合。如果您可以实现一个比较,例如IComparable,它可以基于一个键字段(例如ExamId)进行比较,那么您可以像下面这样使用整数进行示例 var com = from exam1 in timeTable.Exams from exam2 in timeTable.Exams where (exam1 != exam2)

时间表是考试的清单


我怎样才能让com变得清晰,无论它包含的考试顺序如何。我认为它现在正在进行置换,我只需要不同的组合。

如果您可以实现一个比较,例如IComparable,它可以基于一个键字段(例如ExamId)进行比较,那么您可以像下面这样使用整数进行示例

var com = from exam1 in timeTable.Exams
          from exam2 in timeTable.Exams
          where (exam1 != exam2)
          select new List<Exam> { exam1, exam2 };
var exams = timeTable.Exams.ToList();

var com = exams.Select(x => exams.Where(y => exams.IndexOf(y) > exams.IndexOf(x))
    .Select(z => new List<Exam> {x, z}))
    .SelectMany(x => x);

首先定义一个表示无序元组的类:

int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var query = from item1 in array.Select((item, index) => new { item, index })
            from item2 in array.Select((item, index) => new { item, index })
            where (item1.index < item2.index)
            select new Tuple<int, int>(item1.item, item2.item);

foreach (Tuple<int, int> tuple in query)
    Console.WriteLine("{0}\t{1}", tuple.Item1, tuple.Item2);
输出36是正确的,因为有9*8/2=72/2=36个唯一组合9*8表示具有不同元素的有序对的数量,我们除以2得到无序对的数量

针对您的具体情况:

Console.WriteLine(distinct.Count());
你可以试试这个:

var com = (from exam1 in timeTable.Exams
           from exam2 in timeTable.Exams
           where (exam1 != exam2)
           select new UnorderedTuple<Exam, Exam>(exam1, exam2)
          ).Distinct();
工作原理:对于序列1,2,3,4 步骤1:将输入序列分为头列表和尾列表。头列表将始终包含一个元素,尾列表将包含头元素之后的元素。结果:{[1],[2,3,4]},{[2],[3,4]},{[3],[4]},{[],[]} 第二步:加入head和tail列表。结果:[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] 步骤3:展平集合

类似的内容

var com = exams
          .Select(i => new {Head = new [] {i}, Tail = exams.SkipWhile(j => j != i).Skip(1)})
          .Select(l => l.Head.Join(l.Tail, x => 0, x => 0, (a,b) => new {a,b}))
          .SelectMany(l => l);
当然,如果有必要,可以用匿名类型或列表替换元组,但我认为这样更清楚

如果您不想要x,x,一种方法是添加where index1!=index2子句,或者更改范围

此外,如果您只需要序列中包含重复的不同元组,则可以在末尾添加.distinct调用。这将很好地工作,因为元组类型会明智地重写Equals和GetHashCode

优点:

不需要源项的任何内在可比性。 不需要考虑,然后拒绝组合。 缺点:


这只是一种编写带有索引的嵌套for循环的奇特方法。重点放在索引上,而不是项目上,因此有争议的是它不是很关键。

只要在第2行中纠正错误,它应该是列表。我喜欢你保持代码并保持Brevit的简单程度。我认为这是在^2上,如果有可能的话。不可能以任何实际方式定义线性排序。
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var pairs = from item1 in array
            from item2 in array
            where item1 != item2
            select new UnorderedTuple<int, int>(item1, item2);

var distinct = pairs.Distinct();
foreach (var item in distinct) {
    Console.WriteLine("{{{0}, {1}}}", item.Item1, item.Item2);
}
Console.WriteLine(distinct.Count());
var com = (from exam1 in timeTable.Exams
           from exam2 in timeTable.Exams
           where (exam1 != exam2)
           select new UnorderedTuple<Exam, Exam>(exam1, exam2)
          ).Distinct();
var com = exams
          .Select(i => new {Head = new [] {i}, Tail = exams.SkipWhile(j => j != i).Skip(1)})
          .Select(l => l.Head.Join(l.Tail, x => 0, x => 0, (a,b) => new {a,b}))
          .SelectMany(l => l);
var array = timeTable.Exams.ToArray();
var twoTuples = from index1 in Enumerable.Range(0, array.Length)
                from index2 in Enumerable.Range(i, array.Length - i)
                select Tuple.Create(array[index1], array[index2]);