HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Sorting a flattened array

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arraysortingflattened

Problem

I'm using C# in .NET 4. The class holds an array of double that represents a 2-D rectangular matrix but (due to business requirements) must be stored flattened (i.e. a double[]). The class also stores the dimensions of the array. I wish to sort the array by the (virtual) first column. Obviously I have to unflatten it, at least partially, in order to do this, right? I don't see anything in LINQ or System.Array that works on a flattened array.

If there's 1 column, System.Array.Sort() works fine and I don't think it can be improved.

If there's 2 columns, it's not hard to split it into two arrays and again use System.Array.Sort(). If you quickly see a way to improve it great, but if not, I'm happy with it as it stands.

I'm not happy with the code for 3 or more columns (it stinks) and suspect there's some way to improve it.

N.B. In real life the class has get-only properties. It's guaranteed that rows and cols are positive, array != null, and rows*cols==array.Length.

public partial class FlattenedArray
{
    public int rows;
    public int cols;
    public double[] array;
    public void sort()
    {
        double[] keys;
        switch(cols)
        {
            case 1:
                System.Array.Sort(array);
                break;
            case 2:
                keys = new double[rows];
                double[] dItems = new double[rows];
                for (int i=0,k=0; i(keys,dItems);
                for (int i=0,k=0; i(keys,items);
                for (int i=0,k=0; i<rows; i++)
                {
                    int spt = items[i];
                    for (int j = 0; j < cols; j++)
                    {
                        temp[k++] = array[spt++];
                    }
                }
                array = temp;
                break;
            }

Solution

You can improve the code for 3 or more columns and at the same time use it for 1 or 2 columns, by using LINQ:

public partial class FlattenedArray
{
    public int rows;
    public int cols;
    public double[] array;
    public void sort()
    {
        array = (from i in Enumerable.Range(0, rows)
                        select new List(array.ToList().GetRange(cols * i, cols)))
                        .OrderBy(x => x[0])
                        .SelectMany(x => x)
                        .ToArray();     
    }
}


This divides the array into dimensions and sorts it by the first column then flattens it all back to 1D. It will work for any combination of rows and columns as long the conditions you mentioned hold true.

If the data size gets very large you still might want to use Array.Sort for the 1 column data as this code wouldn't be very efficient for 1 column.

Code Snippets

public partial class FlattenedArray
{
    public int rows;
    public int cols;
    public double[] array;
    public void sort()
    {
        array = (from i in Enumerable.Range(0, rows)
                        select new List<double>(array.ToList().GetRange(cols * i, cols)))
                        .OrderBy(x => x[0])
                        .SelectMany(x => x)
                        .ToArray();     
    }
}

Context

StackExchange Code Review Q#51259, answer score: 5

Revisions (0)

No revisions yet.