Как я могу перебрать словарь, который содержит словарь, который содержит другой словарь, который содержит список - PullRequest
1 голос
/ 21 июня 2019

Я хочу изменить значение объектов в списке.Сам список находится в словаре, который находится в словаре, который находится в словаре.Должен ли я перебирать каждый из них в отдельности?Я пробовал это с несколькими foreachs, однако я не был успешным.

Это словарь:

public static Dictionary<int,Dictionary<int,Dictionary<int,List<EventObj>>>> events_list; // <Year,<Month,<Day,Number of Events>>>

Ответы [ 3 ]

3 голосов
/ 21 июня 2019

Лично я предпочитаю SelectMany для такого рода сценариев.

IEnumerable<EventObj> eventObjects = events_list
    .SelectMany(x => x.Value)
    .SelectMany(x => x.Value)
    .SelectMany(x => x.Value);

foreach (EventObj eventObject in eventObjects)
{
    // change the object
}

Или как синтаксис запроса, если вы занимаетесь такими вещами ..;)

IEnumerable<EventObj> eventObjects =
    from years in events_list
    from months in years.Value
    from days in months.Value
    from events in days.Value
    select events;

foreach (EventObj eventObject in eventObjects)
{
    // change the object
}
0 голосов
/ 21 июня 2019

Использование такой сложной структуры может стать неуклюжим и разочаровывающим. Я предлагаю вам создать свой собственный класс, который наследуется от этой структуры, чтобы инкапсулировать логику для добавления данных в структуру и перечисления ее записей. Вот базовая реализация:

public class YearMonthDayTree<T>
    : Dictionary<int, Dictionary<int, Dictionary<int, List<T>>>>
{
    public void Add(int year, int month, int day, T item)
    {
        if (!this.TryGetValue(year,
            out Dictionary<int, Dictionary<int, List<T>>> yearDict))
        {
            yearDict = new Dictionary<int, Dictionary<int, List<T>>>(12);
            this[year] = yearDict;
        }
        if (!yearDict.TryGetValue(month, out Dictionary<int, List<T>> monthDict))
        {
            monthDict = new Dictionary<int, List<T>>(31);
            yearDict[month] = monthDict;
        }
        if (!monthDict.TryGetValue(day, out List<T> dayList))
        {
            dayList = new List<T>();
            monthDict[day] = dayList;
        }
        dayList.Add(item);
    }

    public IEnumerable<(int Year, int Month, int Day, T Item)> Flatten()
    {
        foreach (var yearEntry in this)
        {
            int year = yearEntry.Key;
            foreach (var monthEntry in yearEntry.Value)
            {
                int month = monthEntry.Key;
                foreach (var dayEntry in monthEntry.Value)
                {
                    int day = dayEntry.Key;
                    foreach (var item in dayEntry.Value)
                    {
                        yield return (year, month, day, item);
                    }
                }
            }
        }
    }
}

Пример использования:

var events_list = new YearMonthDayTree<EventObj>();
events_list.Add(2019, 6, 21, new EventObj());
events_list.Add(2019, 6, 22, new EventObj());
events_list.Add(2019, 6, 22, new EventObj());
foreach (var entry in events_list.Flatten())
{
    Console.WriteLine($"{entry.Year}.{entry.Month}.{entry.Day} {entry.Item}");
}

Выход:

2019.6.21 EventObj
2019.6.22 EventObj
2019.6.22 EventObj

0 голосов
/ 21 июня 2019
foreach(var year in events_list.Keys)
    foreach(var month in events_list[year].Keys)
         foreach(var day in events_list[year][month].Keys)
             foreach(var eventObject in events_list[year][month][day])
             {
                 // do stuff
             }

Это должно работать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...