Effective LINQ comparison list?

This may be very similar to this question , but I would like to know the most efficient way in C # and LINQ to compare a list of elements with each other in the same list.

For example, in pseudo code, I would like to do this:

foreach(i in list)    
    foreach(j in list.Except(i))    
        Compare(j,i)

I know that Except accepts an enumeration instead of a single element and may not be a better idea, but this should illustrate my intentions.

Any ideas?

Update:

I think this question was a bit vague. The goal was to iterate over the list twice (using LINQ), skipping a pair (i, i); no matter what Compare(i,j)really doesn't matter to my question.

Then there are two cases where (i,j) == (j,i)and (i,j) != (j,i). For the former, George Duckett's decision below does the trick, but what about the latter? It was here that my initial use of Except was such that both (i,j), and so were evaluated (j,i).

So, to clarify, is there a better way to skip an item in the list besides list.Except(Enumerable.Repeat(i,1))?

+5
source share
4 answers

This will give you all the pairs if the order of the pairs doesn't matter ( Compare(i, j) == Compare(j, i)):

var test = from i in list
           from j in list.SkipWhile(j => j != i)
           where i != j // Remove the self-comparison if you want to
           select Compare(i, j);
+6
source

I do not know if you have a requirement for LINQ, but I will most likely write this code this way when I look at the code after 3 weeks, at first glance I know what is happening.

for(var i = 0; i < list.Count; ++i)
{
    var item = list[i];
    for(var j = i+1; j < list.Count; ++j)
    {
        Compare(item, list[j]);
    }
}

LINQ, :

for(var i = 0; i < list.Count; ++i)
{
    var item = list[i];
    foreach(var j in list.Skip(i+1))
    {
        Compare(item, j);
    }
}
+3

Your requirement needs to be illustrated more, but this may help you:

List<int> list = new List<int>() { 1, 2, 3, 4 };
var result = list.Aggregate((p, q) => p.CompareTo(q) > 0 ? p : q);//Return 4
+1
source

Your question is a bit vague as to what you want to do with the comparison results, but here is the idea:

public static IEnumerable<TResult> Compare<T, TResult>(this IEnumerable<T> source,  Func<T, T, TResult> func)
{
    int i = 0;
    foreach (T item1 in source)
    {
        foreach (T item2 in source.Skip(i))
            yield return func(item1, item2);
        i++;
    }
}

Then you can do whatever you want with the comparison results. For example, with these objects List:

List<string> list = new List<string> { "test", "hello", "foo", "bar" };

You can do it:

var compared = list.Compare((item1, item2) => item1.Equals(item2));
//compared will be IEnumerable<bool> in this case

Or that:

var compared = list.Compare((item1, item2) => new { item1, item2 });
//to get an enumerator of all the different comparisons of the 2 lists
0
source

All Articles