C#: Как пройти по всем элементам из вложенного списка с вложенностью переменных и типом переменной? - PullRequest
0 голосов
/ 16 июня 2020

Я хочу создать функцию

void StringFromNestedList<T>(T theList);

Список может иметь такие типы, как

List<List<List<List<double>>>>
List<List<int>>
List<List<List<SomeCustomType>>>

и т. Д.

Предположим, для каждого элемента, Я хочу активировать функцию, которая должна быть у всех элементов, например ToString()

Если бы я знал количество вложений и размер каждого списка, например, 2 уровня по 4 элемента в каждом, я бы сделал что-то вроде

for (var i = 0; i < 4; i++)
{
    for (var j = 0; j < 4; j++)
    {
        theList[i][j].ToString(); // yes, it doesnt really do anything
    }
}

Но я не знаю, сколько требуется циклов for.

Это выполнимо?

Ответы [ 2 ]

6 голосов
/ 16 июня 2020

Я не уверен, что попытка сделать его generi c принесет вам что-нибудь.

Итак, сначала предположим, что потребуется object.

void StringFromPossibleList(object theList)

Теперь предположим, что мы хотим иметь дело не со списками, а с чем-либо, что можно перечислить. Предположим далее, что эта функция уже работает - тогда для каждого элемента внутри нашего перечислимого мы можем просто вызвать себя рекурсивно!

{
    var enu = theList as IEnumerable;
    if(enu!=null)
    {
        foreach(var item in enu)
        {
            StringFromPossibleList(item);
        }
    }
    else
    {
        theList.ToString();
    }
}

Используя рекурсию, мы получаем столько уровней цикла, сколько получается нам нужно.

0 голосов
/ 16 июня 2020

Альтернативным итеративным решением может быть что-то вроде этого:

    public static IEnumerable<object> FlattenNestedLists(object obj)
    {
        var stack = new Stack();
        stack.Push(obj);
        while (stack.Count > 0)
        {
            var current = stack.Pop();
            if (current is IEnumerable list)
            {
                foreach (var item in list)
                {
                    stack.Push(item);
                }
            }
            else
            {
                yield return current;
            }
        }
    }

Основным преимуществом будет то, что объекты возвращаются и могут быть обработаны чем-то другим. Обратной стороной является потенциальная упаковка, вы можете избежать этой дополнительной проверки, но вам нужно будет учитывать поведение, если списки содержат разнородные объекты.

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