4

I need to sort 2d array rows in ascending order of their first elements, like in example

{{5,7,6},{2,9,6},{4,8,1}} --> {{2,9,6},{4,8,1},{5,7,6}}

I can find max element in row, but i don't now how to sort the rows.

public double[] maxInRow(double[,] n) 
 { 
    double[] result = new double[n.GetLength(0)]; 
    for (int i = 0; i < n.GetLength(0); i++) 
    { 
        double max = 0;
        for (int j = 0; j < n.GetLength(1); j++) 
        { 
        if (max < n[i,j]) 
        { 
            max = n[i,j];
        } 
        } 
    result[i] = max; 
    } 
return result; 
}

Can you advice something?

Thanks in advance!

6 Answers6

8

Sadly with that sintax you are missing the power of linq wich is one of the best components of .Net framework you can try this instead

double[][] x = new double[2][];
x[0] = new double[] { 5, 2, 5 };
x[1] = new double[] { 6, 8, 3 };
x[2] = new double[] { 8, 3, 6 };

var sortedByFisrtVal =  x.OrderBy(y => y[0]);
var sortedBySecondVal = x.OrderBy(y => y[1]);

//trying to guess maybe this is better
var sorted =  x.OrderBy(y => y[0]).ThenBy(y => y[1]).ThenBy(y => y[2]);
bto.rdz
  • 6,636
  • 4
  • 35
  • 52
3

If performance is not critical then you can convert your 2D array into array of rows, sort them via OrderBy from linq providing the Max as the criteria and then convert the result back to 2D array:

        private static T[][] Convert<T>(T[,] source, int firstDim, int secondDim)
        {
            T[][] result = new T[firstDim][];
            for (int i = 0; i < firstDim; i++)
            {
                T[] temp = new T[secondDim];    
                for (int j = 0; j < secondDim; j++)
                {
                    temp[j] = source[i, j];
                }

                result[i] = temp;
            }

            return result;
        }

        private static T[,] ConvertBack<T>(T[][] source, int firstDim, int secondDim)
        {
            var result = new T[firstDim, secondDim];
            for (int i = 0; i < firstDim; i++)
            {
                for (int j = 0; j < secondDim; j++)
                {    
                    result[i, j] = source[i][j];
                }
            }

            return result;
        }

        // usage sample
        double[,] array = { { 5, 7, 6 }, { 2, 9, 6 }, { 4, 8, 1 } };
        int firstDim = array.GetUpperBound(0) + 1;
        int secondDim = array.GetUpperBound(1) + 1;
        double[][] jagged = Convert(array, firstDim, secondDim);

        // actual sort is done here!
        double[][] sorted = jagged.OrderByDescending(row => row.Max()).ToArray();

        double[,] result = ConvertBack(sorted, firstDim, secondDim);
alex.b
  • 4,547
  • 1
  • 31
  • 52
2

You dont need any extra methods. just implement Sort method for 2d array as above.

This Sort algorithm is as same as Sort algorithm for 1D array except that you also need third loop to swap elements of row.

public static void Sort(double[,] n)
{
    for (int i = 0; i < n.GetLength(0) - 1; i++)
    {
        for (int j = i; j < n.GetLength(0); j++)
        {
            if (n[i, 0] > n[j, 0]) // sort by ascending by first index of each row
            {
                for (int k = 0; k < n.GetLength(1); k++)
                {
                    var temp = n[i, k];
                    n[i, k] = n[j, k];
                    n[j, k] = temp;
                }
            }
        }
    }
}

And you can call it like this.

Sort(your2dArray);

Note that algorithm can become very slow of course as noted by Alexei Levenkov. So use it if the performance is not important here.

If you use jagged array instead of 2D array you can make things much faster. Also linq supports 1D array (thus jagged arrays too) which implements IEnumerable and you can use quick sort using OrderBy.

M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
2

2d arrays are not for sorting, but anyway, here is how you can do that

public static class MyAlgorithms
{
    public static void SortByFirstColumn<T>(this T[,] array, IComparer<T> comparer = null)
    {
        // Indirect sorting
        var sortIndex = new int[array.GetLength(0)];
        for (int i = 0; i < sortIndex.Length; i++)
            sortIndex[i] = i;
        if (comparer == null) comparer = Comparer<T>.Default;
        Array.Sort(sortIndex, (a, b) => comparer.Compare(array[a, 0], array[b, 0]));
        // Reorder the array using "in situ" algorithm
        var temp = new T[array.GetLength(1)];
        for (int i = 0; i < sortIndex.Length; i++)
        {
            if (sortIndex[i] == i) continue;
            for (int c = 0; c < temp.Length; c++)
                temp[c] = array[i, c];
            int j = i;
            while (true)
            {
                int k = sortIndex[j];
                sortIndex[j] = j;
                if (k == i) break;
                for (int c = 0; c < temp.Length; c++)
                    array[j, c] = array[k, c];
                j = k;
            }
            for (int c = 0; c < temp.Length; c++)
                array[j, c] = temp[c];
        }
    }
}

and use it as follows

double[,] data = { { 5, 7, 6 }, { 2, 9, 6 }, { 4, 8, 1 } };
data.SortByFirstColumn();

This implementation doesn't suffer performance. For more explanation how it works and some additional options, see my answer to How can I sort a large 2d array C#

Community
  • 1
  • 1
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
1

If you want to order by first column, then by second, then by third and so on for all columns, you can to this:

void Main()
{
    var input = new double[,] {{5,7,6},{2,9,6},{2,5,6},{4,8,1}};

    Sort(input);
    // Input is now:
    // {{2,5,6},{2,9,6},{4,8,1},{5,7,6}}
}

public T[,] Sort<T>(T[,] data) where T : IComparable
{
    // Transform to array of arrays.
    var rows = new T[data.GetLength(0)][];
    for (var i = 0; i< data.GetLength(0); ++i)
    {
        rows[i] = new T[data.GetLength(1)];
        for (var j = 0; j < data.GetLength(1); ++j)
            rows[i][j] = data[i, j];
    }

    // Sort rows using a custom array comparer.
    Array.Sort(rows, new ArrayComparer<T>());

    // Write data back to input array.
    for (var i = 0; i< data.GetLength(0); ++i)
        for (var j = 0; j < data.GetLength(1); ++j)
            data[i, j] = rows[i][j];

    return data;
}

public class ArrayComparer<T> : IComparer<T[]> where T : IComparable
{
    public int Compare(T[] x, T[] y)
    {
        var comparer = Comparer<T>.Default;

        // Compare elements as long as they're different.
        for(var i = 0; i < x.Length; ++i)
        {
            var compareResult = comparer.Compare(x[i], y[i]);
            if (compareResult != 0) return compareResult;
        }
        return 0;
    }
}
Kvam
  • 2,148
  • 1
  • 20
  • 32
0
Array.Sort(double, (a,b)=>{return a[0]-b[0];});
eyllanesc
  • 235,170
  • 19
  • 170
  • 241