我什至不知道该怎么做。
一个例子:
int[][] myArrays = {
new int[] {1, 2, 3},
new int[] {4, 5, 3},
new int[] {1, 2, 3}
};
int[] avgArray = myArrays.//Some LINQ statement to average every Nth element in the second dimension (essentially "flatten" the array)
//avgArray == {2, 3, 3}
到目前为止,我只能想到:
int ndDimLen = myArrays.GetLength(1);
int[] avgArray = new int[ndDimLen];
myArrays.Select(
arr => arr.Select( (n, i) => avgArray[i] += n )
);
avgArray = avgArray.Select( n => n / ndDimLen ).ToArray();
但这不能达到目的,在锯齿状阵列上并不是一个好主意...
此外,我绝对想避免转置,因为在大型阵列上进行操作时速度很慢!
谢谢您的时间!
答案 0 :(得分:2)
您可以在[Columns]
期间遍历[Row]
索引。Length报告它在维度中包含一个[Column]
,您需要对其平均值取平均值。
(为简便起见,使用术语Column
和Row
作为视觉辅助)
一个示例,使用Linq的.Average()计算序列的平均值:
int[][] myArrays = {
new int[] {1, 2, 3},
new int[] {4, 5, 3},
new int[] {1, 2, 3},
};
int column = 2;
double avg = myArrays.Select((arr, i) => myArrays[i][column]).Average();
结果:3
结构更复杂时,我们需要验证当前的[Column]
是否包含一个值:
int[][] myArrays = {
new int[] {1, 2, 3},
new int[] {3, 4, 5},
new int[] {3, 4},
new int[] {1, 2, 3, 4},
new int[] {1},
new int[] {4, 5, 3}
};
int column= 2;
double? avg = myArrays.Select((arr, i) =>
((arr.Length > column) ? myArrays?[i][column] : null)).Average();
Result Column 1: { 1, 3, 3, 1, 1, 4 } => 2.1666666...
Result Column 2: { 2, 4, 4, 2, 5 } => 3.4
Result Column 3: { 3, 5, 3, 3 } => 3.5
Result Column 4: { 4 } => 4
相同的方法,适用于所有[Columns]
:
var Averages = Enumerable.Range(0, myArrays.Max(Arr => Arr.Length))
.Select(col => myArrays
.Select((arr, idx) =>
((arr.Length > col) ? myArrays?[idx][col] : null))
.Average()).ToList();
Enumerable.Range提供了一些灵活性。
上面的代码从int
开始生成一系列0
元素,并将其值递增到数组中 Colums 的数量(Max(Arr => Arr.Length)
选择数组的行包含更多元素)。
因此,您可以使用以下方式对第一列(Index = 0
)中的数字进行平均:
var Averages = Enumerable.Range(0, 1).Select( ... )
或从列 1到3(Indexes 1 to 3
):
var Averages = Enumerable.Range(1, 3).Select( ... )
答案 1 :(得分:1)
是的,可以,但是不能在这个物体上。
myArrays
基本上是一个数组的数组,因此LINQ一次只能看到一行,您不能使其看到列,因为这不是它的工作原理。
您可以做的是首先转换此“表”,即更改列和行的位置。 here已经讨论了如何执行此操作,因此,我将仅介绍给您。
使用知识来转置它,您可以制作将要使用的方法,并在其上使用LINQ,例如:
Transpose(myArray).Select(predicate);
答案 2 :(得分:1)
如果数组的长度不相等,则没有指定所需内容:
int[][] myArrays =
{
new int[] {1, 2},
new int[] {4, 5, 3, 7, 5, 3, 4, 5, 1},
new int[] {1, 2, 3}
};
让我们假设您的数组都具有相同的长度。
如果计划定期使用此功能,请考虑为二维数组编写扩展功能。参见Extension Methods Demystified
public static IEnumerable<int> ToVerticalAverage(this int[][] array2D)
{
if (array2D == null) throw new ArgumentNullException(nameof(array2D);
// if input empty: return empty
if (array2D.Any())
{ // there is at least one row
// check number of columns:
int nrOfColumns = array2D.First().Length;
if (!array2D.All(row => row.Length == nrOfColumns)
{
// TODO: decide what to do if arrays have unequal length
}
// if here, at least one row, all rows have same number of columns
for(int columNr = 0; columNr < nrOfColumns; ++columNr)
{
yield return array2D.Select(row => row[i]).Average();
}
}
// else: no rows, returns empty sequence
}
用法:
int[][] myInputValues = ...
IEnumerable<int> averageColumnValues = myInputValues.ToVerticalAverage();
如果您有多个需要列值的函数,请编写扩展函数以获取列(=转置矩阵)
public static IEnumerable<IEnumerable<int>> Transpose(this int[][] array2D)
{
// TODO: check input
int nrOfColumns = array2D.First().Length;
for(int columNr = 0; columNr < nrOfColumns; ++columNr)
{
yield return array2D.Select(row => row[columnNr];
}
}
public static IEnumerable<int> ToVerticalAverage(this int[][] array2D)
{
// TODO: check input
foreach (IEnumerable<int> column in array2D.Transpose())
{
yield return column.Average();
}