Инициализируйте неровный массив способом LINQ
-
11-09-2019 - |
Вопрос
У меня есть двумерный неровный массив (хотя он всегда прямоугольный), который я инициализирую с помощью традиционного цикла:
var myArr = new double[rowCount][];
for (int i = 0; i < rowCount; i++) {
myArr[i] = new double[colCount];
}
Я подумал, может быть, какая-нибудь функция LINQ даст мне элегантный способ сделать это в одном операторе.Однако самое близкое, что я могу придумать, это следующее:
double[][] myArr = Enumerable.Repeat(new double[colCount], rowCount).ToArray();
Проблема в том, что, похоже, создается единый double[colCount]
и присваивание ссылок на это вместо выделения нового массива для каждой строки.Есть ли способ сделать это, не становясь слишком загадочным?
Решение
double[][] myArr = Enumerable
.Range(0, rowCount)
.Select(i => new double[colCount])
.ToArray();
Другие советы
То, что у вас есть, не будет работать как new
происходит перед вызовом Repeat
.Вам нужно что-то, что также повторяет создание массива.Это может быть достигнуто с помощью Enumerable.Range
способ чтобы сгенерировать диапазон, а затем выполнить Select
операция это сопоставляет каждый элемент диапазона с новым экземпляром массива (как в Ответ Эми Би).
Однако я думаю, что вы пытаетесь использовать LINQ там, где в данном случае это не совсем уместно.То, что у вас было до решения LINQ, просто прекрасно.Конечно, если вам нужен подход в стиле LINQ, подобный Enumerable.Repeat
, вы могли бы написать свой собственный метод расширения, который генерирует новый элемент, например:
public static IEnumerable<TResult> Repeat<TResult>(
Func<TResult> generator,
int count)
{
for (int i = 0; i < count; i++)
{
yield return generator();
}
}
Тогда вы можете назвать это следующим образом:
var result = Repeat(()=>new double[rowCount], columnCount).ToArray();
Поведение является правильным - Repeat()
возвращает последовательность, которая содержит предоставленный объект несколько раз.Вы можете проделать следующий трюк.
double[][] myArr = Enumerable
.Repeat(0, rowCount)
.Select(i => new double[colCount])
.ToArray();
Вы не можете сделать это с помощью Repeat
способ :тот самый element
параметр вычисляется только один раз, поэтому на самом деле он всегда повторяет один и тот же экземпляр.Вместо этого вы могли бы создать метод для выполнения того, что вы хотите, который принимал бы лямбда-выражение вместо значения :
public static IEnumerable<T> Sequence<T>(Func<T> generator, int count)
{
for (int i = 0; i < count; i++)
{
yield return generator();
}
}
...
var myArr = Sequence(() => new double[colCount], rowCount).ToArray();
Я только что написал эту функцию...
public static T[][] GetMatrix<T>(int m, int n)
{
var v = new T[m][];
for(int i=0;i<m; ++i) v[i] = new T[n];
return v;
}
Кажется, работает.
Использование:
float[][] vertices = GetMatrix<float>(8, 3);
О чем
var myArr = new double[rowCount, colCount];
или
double myArr = new double[rowCount, colCount];
Ссылка: http://msdn.microsoft.com/en-us/library/aa691346 (v=против 71).aspx