在“垂直"空间而不是“水平"空间上运行LINQ查询 [英] Operate LINQ queries on 'vertical' rather than 'horizontal' space
问题描述
我什至不知道该怎么做.
一个例子:
I can't figure out how to do this, if even possible.
An example:
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}
到目前为止,我只能想到:
To do this so far, I can only think of:
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();
但是这违背了目的,在锯齿状阵列上并不是一个特别好的主意...
But this defeats the purpose, and isn't a particularly good idea on jagged arrays...
此外,我绝对想避免转置,因为在大型数组上进行操作时速度很慢!
Also, I'd definitely like to avoid transposition, as it's quite a slow operation when operating on large arrays!
谢谢您的时间!
推荐答案
您可以在[Row]
期间遍历[Columns]
索引.长度报告其在维度中包含[Column]
,您需要对其平均值进行平均.
(为简单起见,使用术语Column
和Row
作为视觉辅助)
You could iterate throught the [Columns]
index while a [Row]
.Length reports that it contains a [Column]
in the dimension whose values you need to average.
(Using the terms Column
and Row
for simplicity, as a visual aid)
An example, using Linq's .Average() to compute the average value of the sequence:
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]
是否包含值:
With a more complex structure, we need to verify whether the current [Column]
contains a value:
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]
:
Same method, applied to all the [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();
Max(Arr => Arr.Length)
选择包含较多元素的数组的 Row .
Enumerable.Range gives some flexibility.
The code above generates a series of int
elements starting from 0
and incrementing the value to the number of Colums in the Array (Max(Arr => Arr.Length)
selects the Array's Row containing the higher number of elements).
因此,您可以使用以下方法对第一个列(Index = 0
)中的数字取平均值:
So, you could average the numbers in the first Column only (Index = 0
) with:
var Averages = Enumerable.Range(0, 1).Select( ... )
或从列 1到3(Indexes 1 to 3
):
or from Columns 1 to 3 (Indexes 1 to 3
):
var Averages = Enumerable.Range(1, 3).Select( ... )
这篇关于在“垂直"空间而不是“水平"空间上运行LINQ查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!