Operate LINQ queries on 'vertical' rather than 'horizontal' space

前端 未结 3 1517

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         


        
3条回答
  •  青春惊慌失措
    2020-12-22 12:16

    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();
    

    Result: 3

    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 
    

    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();
    

    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).

    So, you could average the numbers in the first Column only (Index = 0) with:

    var Averages = Enumerable.Range(0, 1).Select( ... )

    or from Columns 1 to 3 (Indexes 1 to 3):

    var Averages = Enumerable.Range(1, 3).Select( ... )

提交回复
热议问题