我正在寻找一种方法将多维数组中的每个值设置为单个值。问题是在编译时维度的数量是未知的 - 它可以是一维的,也可以是四维的。由于foreach
不允许您设置值,我可以通过哪种方式实现此目标?非常感谢。
答案 0 :(得分:4)
虽然这个问题在表面看起来很简单,但它实际上比看起来更复杂。但是,通过认识到访问多维(甚至是锯齿状)数组中的每个位置都是笛卡儿关于数组索引集的产品操作 - 我们可以简化解决方案......并最终编写更优雅的解决方案。
我们将利用Eric Lippert's LINQ Cartesian Product实施来完成繁重的任务。如果您愿意,可以在他的博客上详细了解其工作原理。
虽然此实现特定于访问多维数组的单元格 - 但是应该相对容易地看到如何扩展它以访问锯齿状数组。
public static class EnumerableExt
{
// Eric Lippert's 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() );
}
}
}
将此代码分解为可重用的方法现在是微不足道的,该方法可用于锯齿状或多维数组......或任何可被视为矩形数组的数据结构。
答案 1 :(得分:1)
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");
}
答案 2 :(得分:0)
我认为没有直接的方法可以做到这一点,所以你需要使用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));
}
答案 3 :(得分:0)
Array.Clear
方法将让您清除(设置为默认值)多维数组中的所有元素(即int[,]
)。因此,如果您只想清除数组,可以编写Array.Clear(myArray, 0, myArray.Length);
似乎没有任何方法可以将数组的所有元素设置为任意值。
请注意,如果您将其用于锯齿状数组(即int[][]
),则最终会得到一个对数组的空引用数组。也就是说,如果你写了:
int[][] myArray;
// do some stuff to initialize the array
// now clear the array
Array.Clear(myArray, 0, myArray.Length);
然后myArray[0]
将为null
。
答案 4 :(得分:-1)
您是说要遍历每个元素和(如果可用)数组的每个维度并设置每个值吗?
如果是这种情况,你可以创建一个递归函数,迭代维度并设置值。检查MSDN上的Array.Rank属性和MSDN上的Array.GetUpperBound功能。
最后,我确信通用List<T>
有某种方法可以做到这一点。