2016-04-17 4 views
-1

Мне нужно знать Как изменить или как инициализировать весь элемент массива 2d без цикла?
Я имею в виду, как это сделать, используя методы расширения или используя LINQ !?Как выполнить работу Элемент ForEach из массива 2d без цикла?

Я пытался сделать это, используя расширение «IEnumerable.Cast <>», но результата нет!
И я не знаю почему?

 string[,] m2d = new string[8, 8]; 

     Array.ForEach(m2d.Cast<string>().ToArray(), el => el = "sample1"); 

Там не было никакого результата, даже для цикла ...

 for (int i = 0; i <= m2d.Cast<string>().ToArray().GetUpperBound(0); i++) 
     { 
      m2d.Cast<string>().ToArray()[i] = "sample2"; 
     } 

Но, пожалуйста, забудьте этот цикл!
Просто попробуйте сделать это с помощью выражения одной строки!
как этот, который не работает ...

 m2d.Cast<string>().ToList().ForEach(el => el = "sample3"); 

Спасибо!

+1

«как это сделать, используя методы расширения» - ну, как насчет: public public class ArrayExtensions {public static void SetAllValuesTo (этот массив [,] array, string value) {for (var i = 0; i < array.GetLength (0); i ++) {for (var j = 0; j Corak

ответ

1

Это не работает, потому что с назначением вы просто заменяете значение в коллекции, созданной ToList() или ToArray() методом с новым. Поскольку оба эти метода фактически возвращают новую коллекцию, ваш начальный массив не зависит от изменения, которое вы делаете.

Наиболее очевидным способом, конечно же, является использование двух вложенных циклов. Не знаете, почему вы их избегаете, но если вы действительно хотите использовать ForEach, вы можете перечислять индексы размеров вашего массива, а не его элементы, в виде функционального подхода. Что-то вроде этого:

Enumerable.Range(0, m2d.GetUpperBound(0) + 1).ToList() 
      .ForEach(i => Enumerable.Range(0, m2d.GetUpperBound(1) + 1).ToList() 
       .ForEach(j => m2d[i, j] = "sample")); 
0

Хотя @ ответ Дмитрия довольно много охватывает why the original attempt has failed и то, что вы должны сделать, чтобы исправить, тем не менее, в зависимости от ваших потребностей, вы можете также рассмотреть вопрос о оборачивать каждый пункт/индекс в массиве в некоторых тип ссылочной, который способен изменить исходные элементы массива:

public class MultiDimensionArrayItemReference<T> 
{ 
    private readonly Array _array; 
    private readonly Int32[] _indices; 

    public MultiDimensionArrayItemReference(Array array, params Int32[] indices) 
    { 
     if (array == null) 
      throw new ArgumentNullException(paramName: nameof(array)); 
     if (indices == null) 
      throw new ArgumentNullException(paramName: nameof(indices)); 
     this._array = array; 
     this._indices = indices; 
    } 

    public IReadOnlyCollection<Int32> Indices 
    { 
     get 
     { 
      return this._indices.ToList().AsReadOnly(); 
     } 
    } 

    public T Value 
    { 
     get 
     { 
      return (T)this._array.GetValue(this._indices); 
     } 
     set 
     { 
      this._array.SetValue(value, this._indices); 
     } 
    } 

    public override string ToString() 
    { 
     return $"[{String.Join(", ", this._indices)}]:{this.Value}"; 
    } 
} 


public static class MultiDimensionArrayItemReferenceExtensions 
{ 
    // That's for the two-dimensional array, but with some effort it can be generalized to support any arrays. 
    public static IEnumerable<MultiDimensionArrayItemReference<T>> EnumerateReferenceElements<T>(this T[,] array) 
    { 
     if (array == null) 
      throw new ArgumentNullException(paramName: nameof(array)); 

     // Assume zero-based 
     var rows = array.GetLength(0); 
     var columns = array.GetLength(1); 

     for (int row = 0; row < rows; row++) 
     { 
      for (int col = 0; col < columns; col++) 
      { 
       yield return new MultiDimensionArrayItemReference<T>(
        array, 
        row, 
        col); 
      } 
     } 
    } 
} 

...

private static void PrintArray<T>(T[,] array) 
{ 
    // Assume zero-based 
    var rows = array.GetLength(0); 
    var columns = array.GetLength(1); 

    for (int row = 0; row < rows; row++) 
    { 
     for (int col = 0; col < columns; col++) 
     { 
      Console.Write("{0, 7}", array[row, col]); 
     } 
     Console.WriteLine(); 
    } 
} 

...

var array = new [,] 
{ 
    { "a1", "a2" }, 
    { "b1", "b2" } 
}; 

PrintArray(array); 
Console.WriteLine(); 

var elements = array 
    .EnumerateReferenceElements() 
    .ToList(); 

foreach (var elem in elements) 
{ 
    Console.WriteLine(elem); 
} 

elements.ForEach(
    elem => 
     elem.Value = elem.Value + "_n"); 

Console.WriteLine(); 
PrintArray(array); 

Это приведет к следующему выходу:

 
    a1  a2 
    b1  b2 

[0, 0]:a1 
[0, 1]:a2 
[1, 0]:b1 
[1, 1]:b2 

    a1_n a2_n 
    b1_n b2_n 

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

Смежные вопросы