C #: setting all values ​​in an array with arbitrary sizes

I am looking for a way to set each value in a multidimensional array to one value. The problem is that the number of dimensions is unknown at compile time - it can be one-dimensional, it can be 4-dimensional. Since it foreachdoes not allow setting values, how could I achieve this goal? Many thanks.

+3
source share
5 answers

Although this problem seems simple on the surface, it is actually more complex than it looks. However, recognizing that visiting each position in a multidimensional (or even cogged) array is a Cartesian operation of the product on a set of array indices, we can simplify the solution ... and ultimately write a more elegant solution.

We are going to use Eric Lippert LINQ Cartesian Product to make a heavy lift. You can read more about how this works on your blog if you want.

While this implementation is specific to visiting the cells of a multidimensional array, it should be relatively easy to see how to expand it to visit the notched array.

public static class EnumerableExt
{
    // Eric Lippert Cartesian Product operator...
    public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
          this IEnumerable<IEnumerable<T>> sequences)
    {
        IEnumerable<IEnumerable<T>> emptyProduct = 
                   new[] { Enumerable.Empty<T>() };
        return sequences.Aggregate(
          emptyProduct,
          (accumulator, sequence) =>
            from accseq in accumulator
            from item in sequence
            select accseq.Concat(new[] { item }));
    }
}

class MDFill
{
    public static void Main()
    {
        // create an arbitrary multidimensional array
        Array mdArray = new int[2,3,4,5];

        // create a sequences of sequences representing all of the possible
        // index positions of each dimension within the MD-array
        var dimensionBounds = 
            Enumerable.Range(0, mdArray.Rank)
               .Select(x => Enumerable.Range(mdArray.GetLowerBound(x),
                      mdArray.GetUpperBound(x) - mdArray.GetLowerBound(x)+1));

        // use the cartesian product to visit every permutation of indexes
        // in the MD array and set each position to a specific value...
        int someValue = 100;
        foreach( var indexSet in dimensionBounds.CartesianProduct() )
        {
            mdArray.SetValue( someValue, indexSet.ToArray() );
        }
    }
}

, , ... , .

+4

Array.Length , , ( ) :

for(var i=0; i<myMDArray.Length; i++)
   for(var j=0; j < myMDArray[i].Length; i++)
      DoSomethingTo(myMDArray[i][j]);

( ), ; .

, :

public void SetValueOn(Array theArray, Object theValue)
{
   if(theArray[0] is Array) //we haven't hit bottom yet
      for(int a=0;a<theArray.Length;a++)
         SetValueOn(theArray[a], theValue);
   else if(theValue.GetType().IsAssignableFrom(theArray[0].GetType()))
      for(int i=0;i<theArray.Length;i++)
         theArray[i] = theValue;
   else throw new ArgumentException(
         "theValue is not assignable to elements of theArray");
}
+1

, , Rank SetValue ( ).

, ( ):

bool IncrementLastIndex(Array ar, int[] indices) {
  // Return 'false' if indices[i] == ar.GetLength(i) for all 'i'
  // otherwise, find the last index such that it can be incremented,
  // increment it and set all larger indices to 0
  for(int dim = indices.Length - 1; dim >= 0; dim--) { 
    if (indices[dim] < ar.GetLength(dim)) {
      indices[dim]++;
      for(int i = dim + 1; i < indices.Length; i++) indices[i] = 0;
      return;
    }
  }
}

void ClearArray(Array ar, object val) {
  var indices = new int[ar.Rank];
  do {
    // Set the value in the array to specified value
    ar.SetValue(val, indices);
  } while(IncrementLastIndex(ar, indices));
}
0

Array.Clear ( ) (.. int[,]). , , Array.Clear(myArray, 0, myArray.Length);

, .

, jagged (.. int[][]), . , :

int[][] myArray;
// do some stuff to initialize the array
// now clear the array
Array.Clear(myArray, 0, myArray.Length);

myArray[0] null.

0

, ( ) ?

If in this case you create a recursive function that iterates the measurements and sets the values. Check the Array.Rank property on MSDN and Array.GetUpperBound on MSDN.

Finally, I am sure that the general List<T>has some way to do this.

-1
source

Source: https://habr.com/ru/post/1766787/


All Articles