Как я могу преобразовать список <> в многомерный массив? - PullRequest
5 голосов
/ 24 марта 2009

У меня есть следующая подпись метода:

public void MyFunction(Object[,] obj)

Я создаю этот объект:

List<List<Object>> obj = new List<List<Object>>;

Есть ли простой способ преобразовать это в Object[,]?


UPDATE:

Дело в том, что мне нравится использовать List s, потому что я могу легко добавить новый элемент. Есть ли способ, которым я могу объявить мой List<> объект, чтобы удовлетворить эту потребность? Я знаю количество столбцов в моем Object[,], но не количество строк.

Ответы [ 4 ]

11 голосов
/ 24 марта 2009

Нет. На самом деле, это не обязательно совместимые массивы.

[,] определяет многомерный массив. List<List<T>> будет больше соответствовать неровному массиву (object[][]).

Проблема в том, что в вашем исходном объекте каждый List<object>, содержащийся в списке списков, может иметь разное количество объектов. Вам нужно создать многомерный массив самой большой длины внутреннего списка и заполнить его нулевыми значениями или что-то в этих строках, чтобы оно совпадало.

6 голосов
/ 24 марта 2009

Вы не получите очень простого решения для этого (то есть несколько строк). Класс LINQ / Enumerable не поможет вам в этом случае (хотя он мог бы, если вы хотите использовать зубчатый массив, т.е. Object[][]). Простая вложенная итерация, вероятно, является лучшим решением в этом случае.

public static T[,] To2dArray(this List<List<T>> list)
{
    if (list.Count == 0 || list[0].Count == 0)
        throw new ArgumentException("The list must have non-zero dimensions.");

    var result = new T[list.Count, list[0].Count];
    for(int i = 0; i < list.Count; i++)
    {
        for(int j = 0; j < list[i].Count; j++)
        {
            if (list[i].Count != list[0].Count)
                throw new InvalidOperationException("The list cannot contain elements (lists) of different sizes.");
            result[i, j] = list[i][j];
        }
    }

    return result;
}

Я включил немного обработки ошибок в функцию только потому, что она может вызвать некоторые запутанные ошибки, если вы используете ее во вложенном списке без квадратов.

Этот метод, конечно, предполагает, что каждый List<T>, содержащийся в качестве элемента родителя List, имеет одинаковую длину. (В противном случае вам действительно нужно использовать зубчатый массив.)

2 голосов
/ 05 августа 2015

Вот решение, использующее расширение Aggregate Линка.

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

public static T[,] To2DArray<T>(this List<List<T>> lst)
{

    if ((lst == null) || (lst.Any (subList => subList.Any() == false)))
        throw new ArgumentException("Input list is not properly formatted with valid data");

    int index = 0;
    int subindex;

    return 

       lst.Aggregate(new T[lst.Count(), lst.Max (sub => sub.Count())],
                     (array, subList) => 
                        { 
                           subindex = 0;
                           subList.ForEach(itm => array[index, subindex++] = itm);
                           ++index;
                           return array;
                         } );
}

Тест / Использование

var lst = new List<List<string>>() { new List<string>() { "Alpha", "Beta", "Gamma" },
                                     new List<string>() { "One", "Two", "Three" },
                                     new List<string>() { "A" }
                                 };
var newArray = lst.To2DArray();

Результат:

enter image description here

0 голосов
/ 24 марта 2009

Если говорить прямо, ответ - нет, не просто.

Возможно, вы хотели бы отредактировать свой вопрос, чтобы дать нам дополнительную информацию о том, зачем нужны эти объявления, и мы можем помочь вам с вашей корневой проблемой?


Re ваше обновление:

Полагаю, вы не можете изменить функцию, в которую вы хотите передать это.

Я не понимаю, почему вы не можете просто использовать object[,] для начала. Это моя рекомендация.

Я сомневаюсь, что это поможет вам в вашей ситуации, но это может упростить вам работу с некоторыми массивами. Знаете ли вы о .ToArray() метод на List?

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