我有一个二维object[,]
数组,其中包含行和列的矩阵(object[nRows, nColumns]
)。
我想将其分块为一批行-例如我可以枚举成批的1,000行。
总而言之,我正在寻找能执行以下操作但针对二维数组(source)的C#代码:
private IEnumerable<T[]> SplitArray<T>(T[] sourceArray, int rangeLength)
{
int startIndex = 0;
do
{
T[] range = new T[Math.Min(rangeLength, sourceArray.Length - startIndex)];
Array.Copy(sourceArray, startIndex, range, 0, range.Length);
startIndex += rangeLength;
yield return range;
}
while (startIndex < sourceArray.Length);
}
这种为[,]数组修改代码的尝试失败了-第一次迭代后,行/列开始变得混乱:
private IEnumerable<T[,]> SplitArray<T>(T[,] sourceArray, int rangeLength)
{
int startIndex = 0;
do
{
T[,] range = new T[Math.Min(rangeLength, sourceArray.GetLength(0) - startIndex), sourceArray.GetLength(1)];
Array.Copy(sourceArray, startIndex, range, 0, range.Length);
startIndex += rangeLength;
yield return range;
}
while (startIndex < sourceArray.GetLength(0));
}
答案 0 :(得分:2)
这将解决您的代码问题。由于Array.Copy威胁数组是一维的,因此您必须乘以列数才能获得某些位置的元素总数:
private IEnumerable<T[,]> SplitArray<T>(T[,] sourceArray, int rangeLength)
{
int startIndex = 0;
do
{
T[,] range = new T[Math.Min(rangeLength, sourceArray.GetLength(0) - startIndex/sourceArray.GetLength(1)), sourceArray.GetLength(1)];
Array.Copy(sourceArray, startIndex, range, 0, range.Length);
startIndex += rangeLength*sourceArray.GetLength(1);
yield return range;
}
while (startIndex < sourceArray.Length);
}
答案 1 :(得分:1)
通过使用GetLength(int dimension),您可以查看数组的特定维的长度,然后对其进行迭代。您还需要将其他维度用作常量,并确保整个内容与Array.Rank值匹配。从那里,只需通过Array.GetValue(int[])查找值。由于Array不是通用的,因此可能会有点困难:
public static IEnumerable<T> GetRow<T>(this Array source, int dimension, params int[] fixedDimensions)
{
if(source == null) throw new ArgumentNullException(nameof(source));
if(!typeof(T).IsAssignableFrom(source.GetType().GetElementType()) throw new OperationException($"Cannot return row of type {typeof(T)} from array of type {source.GetType().GetElementType()}");
if(fixedDimensions == null) fixedDimensions = new T[0];
if(source.Rank != fixedDimensions.Length + 1) throw new ArgumentException("Fixed dimensions must have exactly one fewer elements than dimensions in source", nameof(fixedDimensions));
if(dimension > source.Rank) throw new ArgumentException($"Cannot take dimension {dimension} of an array with {source.Rank} dimensions!", nameof(dimension));
if(dimension < 0) throw new ArgumentException("Cannot take a negative dimension", nameof(dimension));
var coords = dimension == source.Rank
? fixedDimensions
.Concat(new [] { 0 })
.ToArray()
: fixedDimensions
.Take(dimension)
.Concat(new [] { 0 })
.Concat(fixedDimensions.Skip(dimension))
.ToArray();
var length = source.GetLength(dimension);
for(; coords[dimension] < length; coords[dimension]++)
{
yield return (T)source.GetValue(coords);
}
}
答案 2 :(得分:1)
我认为您正在寻找这样的东西:
private static List<T[]> SplitArray<T>(T[,] sourceArray)
{
List<T[]> result = new List<T[]>();
int rowCount = sourceArray.GetLength(0);
for (int i = 0; i < rowCount; i++)
{
result.Add(GetRow(sourceArray, i));
}
return result;
}
private static T[] GetRow<T>(T[,] sourceArray, int rownumber)
{
int columnCount = sourceArray.GetLength(1);
var row = new T[columnCount];
for (int i = 0; i < columnCount; i++)
{
row[i] = sourceArray[rownumber, i];
}
return row;
}