简体   繁体   中英

Nested foreach to LINQ in multi-level dictionary

I would like to simplify below nested foreach loops using LINQ but couldn't figure out the way. I guess I can use SelectMany using lambda but not sure. I want to create list of objects of ClassA after this nested iteration. Any help is appreciated:

public List<ClassA> GetLists(Dictionary<string, Dictionary<IEnumerable, Dictionary<string, ClassB>>> groups)
{
    var retOutput = new List<ClassA>();

    foreach (KeyValuePair<string, Dictionary<IEnumerable, Dictionary<string, ClassB>>> group1 in groups)
    {
        foreach (KeyValuePair<IEnumerable, Dictionary<string, ClassB>> group2 in group1.Value)
        {
            foreach (KeyValuePair<string, ClassB> group3 in group2.Value)
            {
                GetList(retOutput, group1.Key, 
                    group2.Key, 
                    group3);
            }
        }
    }

    return retOutput;
}

private static void GetList(List<ClassA> retOutput, 
    string group1Key, 
    IEnumerable group2Key, 
    KeyValuePair<string, ClassB> group3)
{
    List<List<string>> itemIdsLists = group3.Value.ItemId.IntoChunks(2000);
    foreach (var itemIdList in itemIdsLists)
    {
        var currentRequest = new ClassA
        {
            TransactionType = group1Key,
            Filters = new Dictionary<string, object>(),
            ItemIds = new List<string>(),
            PropStreamsDict = new Dictionary<string, Tuple<long, string>>()
        };
        if (group2Key is Dictionary<string, object>)
        {
            currentRequest.Filters = (Dictionary<string, object>)group2Key;
        }
        currentRequest.PropStreamsDict.Add(group3.Key, Tuple.Create(group3.Value.StreamId,
            group3.Value.Uom));
        currentRequest.ItemIds.AddRange(itemIdList);
        retOutput.Add(currentRequest);
    }
}

You should use SelectMany to make nested foreach .

Here what I come up with:

public List<ClassA> GetLists(Dictionary<string, Dictionary<IEnumerable, Dictionary<string, ClassB>>> groups)
{
    return groups
        .SelectMany(grp1 => grp1.Value
            .SelectMany(grp2 => grp2.Value
                .SelectMany(grp3 => grp3.Value.ItemId
                    .IntoChunks(2000)
                    .Select(itemIdList =>
                        new ClassA
                        {
                            TransactionType = grp1.Key,
                            Filters = grp2.Key is Dictionary<string, object> ? 
                                (Dictionary<string, object>)grp2.Key :
                                new Dictionary<string, object>(),
                            ItemIds = new List<string>(itemIdList),
                            PropStreamsDict = new Dictionary<string, Tuple<long, string>>
                            {
                                { grp3.Key, Tuple.Create(grp3.Value.StreamId, grp3.Value.Uom) }
                            }
                        }
                    )
                )
            )
        )
        .ToList();
}

You didn't post your ClassA and ClassB so I had to guess.

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