Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

linq query to find distinct combinations of list items taking 2 at a time c#

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

timeTable is a list of Exams

How can i get com to be distinct no matter what the order of the exams are that it contains. I think it is doing permutations now i need only distinct combinations.

like image 641
Romaine Carter Avatar asked Nov 19 '25 22:11

Romaine Carter


2 Answers

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);
like image 179
Jay Avatar answered Nov 21 '25 11:11

Jay


If you can implement a comparison such as IComparable<Exam> (which could, for example, compare based on a key field such as ExamId), you could possibly do it like this (showing example using integers)

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

var query = from item1 in array
            from item2 in array
            where (item1.CompareTo(item2) < 0)
            select new Tuple<int, int>(item1, item2);

foreach (Tuple<int, int> tuple in query)
    Console.WriteLine("{0}\t{1}", tuple.Item1, tuple.Item2);

Without implementing an interface, the same logic could be expressed as a Func<> inline or declared seperately, depending on how complicated the logic might be.

Func<int, int, int> itemComparer = (x, y) => x.CompareTo(y);
// in your case, perhaps 
// Func<Exam, Exam, int> examComparer = (exam1, exam2) => exam1.Id.CompareTo(exam2.Id);

var query = from item1 in array
            from item2 in array
            where itemComparer(item1, item2) < 0
            select new Tuple<int, int>(item1, item2);

Otherwise, you might consider going by indexes and only looking at item2 when its position within the sequence is greater than item1.

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);
like image 45
Anthony Pegram Avatar answered Nov 21 '25 12:11

Anthony Pegram