Comparing each element with each other element in a list

16,492

Solution 1

It sounds like you might want something like:

for (int i = 0; i < list.Count - 1; i++)
{
    for (int j = i + 1; j < list.Count; j++)
    {
        // Use list[i] and list[j]
    }
}

You definitely can do this with LINQ:

var pairs = from i in Enumerable.Range(0, list.Count - 1)
            from j in Enumerable.Range(i + 1, list.Count - i - 1)
            select Tuple.Create(list[i], list[j]);

I'm not sure it's any clearer though...

EDIT: Another alternative which is less efficient, but potentially clearer:

var pairs = from i in Enumerable.Range(0, list.Count - 1)
            let x = list[i]
            from y in list.Skip(i + 1)
            select Tuple.Create(x, y);

Solution 2

If you are using C# 7 or later, you can take advantage of the ValueTuple type. It offers increased usability and performance.

public static IEnumerable<(T, T)> GetAllPairs<T>(IList<T> source)
{
    return source.SelectMany((_, i) => source.Where((_, j) => i < j),
        (x, y) => (x, y));
}

Usage example:

foreach ((int x, int y) in GetAllPairs(new[] { 0, 1, 2 }))
{
    // Execute code
    Console.WriteLine($"Pair: {x}, {y}");
}

Output:

Pair: 0, 1
Pair: 0, 2
Pair: 1, 2
Share:
16,492
Wilson
Author by

Wilson

Updated on July 05, 2022

Comments

  • Wilson
    Wilson almost 2 years

    What is the best way to write a control structure that will iterate through each 2-element combination in a list?

    Example:

    {0,1,2}
    

    I want to have a block of code run three times, once on each of these:

    {0,1}
    {1,2}
    {0,2}
    

    I tried the following

    foreach (int i in input)
    {
        foreach (int j in input.Where(o => o != i))
        {
            //Execute code
        }
    }
    

    However, this won't work when a list has two of the same elements. With

    {0,2,0}
    

    I would still want to compare elements 0 and 0. The value is irrelevant.