3

assume i create this code to generate the idv-th random number. But i have a difficulty in sorting the array depends on the last column.

let say the individual size is [idv, width] = [8,6] and i want to sort all the row with column 6th... and i want to take the 4 top list in the array after it sorted. How can i implement this case to the 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 you

2
  • 1
    I suggest using jagged arrays double[][] individual instead of 2d ones. Commented May 21, 2015 at 9:46
  • as Dmitry wrote. multidimensional arrays are an half-baked/incomplete "subsystem". Commented May 21, 2015 at 9:47

3 Answers 3

3

I suggest you using jagged arrays double[][] instead of 2d ones double[,]. Jagged array is just an array of array which you can easily sort, filter, etc. usually with a help of 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();

One more Linq to test the results:

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

  Console.Write(test);

The result is

11  12  13  14  15  16
21  22  23  24  25  26
31  32  33  34  35  36
41  42  43  44  45  46
Sign up to request clarification or add additional context in comments.

Comments

2

If you use multidimensional arrays, there's no easy way to work with them using LINQ, you'll need to rely on 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 need only top 4 rows, you can add Take(4) before ToList() call and adjust result array creation and copying of values into it appropriately.

Multidimenional arrays are more efficient and use less memory, so if your arrays are big enough or you need to work with them faster, you may need to write a little more code and use multidimenional arrays instead of jagged arrays which are easier to work with.

Comments

0

For rectangular array [,] you can copy the desired column in a single-dimensional array together with indices, sort it, and then get rows with 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]...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.