Link to home
Start Free TrialLog in
Avatar of deleyd
deleydFlag for United States of America

asked on

Linq to select all pairs from a list

I'm looking for a C# LINQ statement that will return all pairs from a list.

I've seen solution of the form:
var combinations = from item1 in list
                   from item2 in list
                   where item1 < item2
                   select Tuple.Create(item1, item2);

Open in new window

My problem is the (item1 < item2). What if these are objects that can't be compared?

The non-Linq solution would be something like:
for (int I=0; I < list.Count; ++I)
    for (int j = I+1; j < list.Count; ++j)
        pairs.Add(new Pair(list[I], list[j]);

Open in new window


So if list = {a,b,c,d,e}
the pairs would be:
{a,b}
{a,c}
{a,d}
{a,e}
{b,c}
{b,d}
{b,e}
{c,d}
{c,e}
{d,e}

(An item is not paired with itself)
And we don't want both {a,e} and {e,a}. Just the first one.
Avatar of Eduard Ghergu
Eduard Ghergu
Flag of Romania image

Hi,

You can create a function like Compare or something that can be used in the where clause:

 where Compare(item1, item2)
Avatar of deleyd

ASKER

If the list is ordered, is there a way to leverage the order of the list? Some way of converting the for loops using indexes, where it's easy to compare indexes, into a Linq statement?
Hi,
If the list is ordered, is there a way to leverage the order of the list?
I don’t understand the question.
In a list, the item index is just a way to get access to it.
If you want, you can use an OrderedCollection or OrderedDictionary
Avatar of deleyd

ASKER

(Sorry I haven't replied sooner.)

Well in the sample code using for loops a compare function would be comparing I with j.

(Should be a lowercase i. The spelling 'corrector' kept disagreeing.)

But in a Linq statement I don't have access to I and j. (Or do I?)
Hi,
Your function will have access to i and j, the only thing is that the function should return a bool.
Avatar of deleyd

ASKER

Can I create a Linq statement something like:
var combinations = from item1 in list
                   from item2 in list
                   where j < i
                   select Tuple.Create(item1, item2);

Open in new window

What would be the correct syntax for that?
Hi,
In the end, what is i and what is j?
If you’ll start with
var combinations = from item1 in list
                   from item2 in list;
You be able to add any conditions do you want and select whatever you want.
Avatar of deleyd

ASKER

How about can I wedge in the .Distinct() qualifier so there are no duplicates?
var combinations = from item1 in list
                   from item2 in list
                   where item1 != item2
                   select Tuple.Create(item1, item2);
var pairs = conbinations.Distinct();

Open in new window

Is there a way to do this in one step instead of two?
ASKER CERTIFIED SOLUTION
Avatar of Eduard Ghergu
Eduard Ghergu
Flag of Romania image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of deleyd

ASKER

OK so I have to put parentheses around it all and then append a .Distinct()

Is Linq smart enough to do this in an efficient manner? Or does it create list.Count() squared items and then filter out the duplicates?

Actually it's looking like it's not too much of a hit if it creates all the possible combinations and then just weeds out the duplicates, so thank you this is the answer I was looking for.

Oh is there a way to get the Distinct without using the dot format?
Avatar of deleyd

ASKER

is there a way to get the Distinct without using the dot format? \

Thank you for your help!
Hi!
As long as Distinct is applied to the custom result, no. Please, let me know if you need more help.