简体   繁体   中英

C# iterate over two lists - exchangable inner / outer loop

I need to iterate over three lists and process each combination. Order of the most outer and second level loop ( list1 / list2 ) depends on some ordering rules. Moreover I have some logic before and after the last ( list3 ) foreach loop. ProcesPair method uses all three items and depends on their order.

        if (order == Order.Right)
        {
            foreach (var a in list1)
            {
                foreach (var b in list2)
                {
                    DoSomethingBefore();

                    foreach (var c in list3)
                    {
                        ProcessPair(a, b, c);
                    }

                    DoSomethingAfter();
                }
            }
        }
        else if (order == Order.Down)
        {
            foreach (var b in list2)
            {
                foreach (var a in list1)
                {
                    DoSomethingBefore();

                    foreach (var c in list3)
                    {
                        ProcessPair(a, b, c);
                    }

                    DoSomethingAfter();
                }
            }
        }

Is it possible to make it somehow more elegant? I meen, how to reduce loops in code, something like Zip function but each with each other.

Nested loops are indicator for LINQ SelectMany . Hence the equivalent of the sample code could be like this:

var pairs = 
    order == Order.Right ? list1.SelectMany(a => list2, (a, b) => new { a, b }) ?
    order == Order.Down ? list2.SelectMany(b => list1, (b, a) => new { a, b }) :
    null;

if (pairs != null)
{
    foreach (var pair in pairs)
    {
        DoSomethingBefore();
        foreach (var c in list3)
        {
            ProcessPair(pair.a, pair.b, c);
        }
        DoSomethingAfter();
    }
}

Or just refactor the repeating code into a separate method:

void ProcessPairs(List<int> list1, List<int> list2, List<int> list3)
{
    foreach (var a in list1)
        foreach (var b in list2)
        {
            DoSomethingBefore();

            foreach (var c in list3)
                ProcessPair(a, b, c);

            DoSomethingAfter();
        }        
}

and then

    if (order == Order.Right)
        ProcessPairs(list1, list2, list3);
    else if (order == Order.Down)
        ProcessPairs(list2, list1, list3);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM