Multilevel sorting of array columns

Suppose I am generating this code to generate the idv th random number. But I find it difficult to sort the array, depends on the last column.

let's say the individual size is [idv, width] = [8,6] and I want to sort the whole row with the 6th column ... and I want to take the 4 top list in the array after sorting it. How can I implement this case for code?

public static void population(double[,] individual, int width, int idv, Random rnd)
    {
        for (int i = 0; i < idv; i++)
        {
            Console.Write("individual {0} :\t", i+1);
            for (int j = 0; j < width; j++)
            {
                individual[i, j] = Math.Round(rnd.NextDouble() * 10, 2);
                Console.Write("{0} ", individual[i, j]);
            }
            Console.WriteLine("\n");
        }
    }

      

thank

+3


source to share


3 answers


I suggest you use jagged arrays double[][]

instead of 2d double[,]

. Jagged array is an array of arrays that you can easily sort, filter, etc. Usually using Linq:

  double[][] individual = new double[][] {
    new double[] {81, 82, 83, 84, 85, 86},
    new double[] {11, 12, 13, 14, 15, 16},
    new double[] {41, 42, 43, 44, 45, 46},
    new double[] {31, 32, 33, 34, 35, 36},
    new double[] {51, 52, 53, 54, 55, 56},
    new double[] {21, 22, 23, 24, 25, 26},
    new double[] {61, 62, 63, 64, 65, 66},
    new double[] {71, 72, 73, 74, 75, 76},
  };

  double[][] fragment = individual
    .OrderBy(line => line[line.GetUpperBound(0)]) // by last column
    .Take(4) 
    .ToArray();

      

Another Linq to check the results:



  String test = String.Join(Environment.NewLine, fragment
    .Select(line => String.Join("\t", line)));

  Console.Write(test);

      

Result

11  12  13  14  15  16
21  22  23  24  25  26
31  32  33  34  35  36
41  42  43  44  45  46

      

+3


source


If you are using multidimensional arrays, there is no easy way to work with them using LINQ, you will need to rely on the good old for

.

static void Main ()
{
    // Input array
    double[,] u = {
        { 1, 9, 3 },
        { 0, 3, 4 },
        { 3, 4, 5 },
        { 3, 6, 8 },
        { 3, 5, 7 },
    };

    // Get dimension sizes, specify column to order by
    int count = u.GetLength(0), length = u.GetLength(1), orderBy = 2;
    // Result array
    double[,] v = new double[count, length];
    // Construct a list of indices to sort by
    var indices = Enumerable.Range(0, count).OrderBy(i => u[i, orderBy]).ToList();
    // Copy values from input to output array, based on these indices
    for (int i = 0; i < count; i++)
        for (int j = 0; j < length; j++)
            v[i, j] = u[indices[i], j];

    PrintArray(u);
    Console.WriteLine();
    PrintArray(v);
}

static void PrintArray (double[,] a)
{
    for (int i = 0; i < a.GetLength(0); i++) {
        for (int j = 0; j < a.GetLength(1); j++)
            Console.Write(a[i, j]);
        Console.WriteLine();
    }
}

      



If you only want the top 4 rows, you can add Take(4)

before the call ToList()

and adjust the creation of the result array and copy the values ​​into it accordingly.

Multi-element arrays are more efficient and use less memory, so if your arrays are large enough or you need to work with them faster, you may need to write a little more code and use multidimensional matrices instead of jagged arrays, which are easier to work with.

+2


source


For a rectangular array, [,]

you can copy the desired column into a one-dimensional array along with the indices, sort it, and then get the rows with the first 4 indices.

static IEnumerable<Tuple<int, double>> GetColumn(int columnIndex, double[,] a)
{
    for (int i = a.GetLowerBound(0); i <= a.GetUpperBound(0); i++)
        yield return Tuple.Create(i, a[i, columnIndex]);
}

double [,] data = ...;
var column = GetColumn(4, data);
var top4Indices = column.OrderBy(v => v.Second)
                        .Take(4)
                        .Select(v => v.First);

foreach (int i in top4Indices)
    for (int j = data.GetLowerBound(1); j <= data.GetUpperBound(1); j++)
        data[i, j]...

      

0


source







All Articles