在“垂直"空间而不是“水平"空间上运行LINQ查询 [英] Operate LINQ queries on 'vertical' rather than 'horizontal' space

查看:82
本文介绍了在“垂直"空间而不是“水平"空间上运行LINQ查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我什至不知道该怎么做.
一个例子:

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],您需要对其平均值进行平均.
(为简单起见,使用术语ColumnRow作为视觉辅助)

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)

使用Linq的

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆