tags:

views:

235

answers:

2

I have the array of integers: d[]. for example(7 columns and some rows):

4 1 8 0 3 2 6

7 0 4 9 1 1 5

0 6 1 3 5 2 0

and so on. At compile time I do not know how many columns has array d. And I do not know at compile time which columns to use to orderby.

For example need to sort by: d[5], d[2], d[0], d[3]. But at run time I know order of the columns to sort. For example column indexes: 5, 2, 0, 3 which mean d[5], d[2], d[0], d[3] columns. How can I orderby array d using this indexes of columns?

A: 

I suggest using DataTable to create a column structure at runtime & adding rows. And then sort it using Column's name.

e.g. DataTable.Sort = "Column5 ASC, Column2 ASC" (pseudocode).

shahkalpesh
Thanks for an answer. I'll do it if there is no LINQ solution.But I guess the LINQ was invented exactly to replace the DataTable and so on. Any LINQ/C# idea?
Ildar
@lldar - LINQ doesn't really *replace* DataTable; they have different use-cases, and can be used in combination if you want.
Marc Gravell
+2  A: 

Assuming you are using a jagged array (int[][]), then you can use LINQ by combining OrderBy and ThenBy:

using System;
using System.Collections.Generic;
using System.Linq;
static class Program
{
    static void Main()
    {
        int[][] data = {
          new[]{4,1,8,0,3,2,6},
          new[]{7,0,4,9,1,1,5},
          new[]{0,6,1,3,5,2,0}};
        int[] sortCols = { 5, 2, 0, 3 };

        IEnumerable<int[]> qry = data;
        if (sortCols.Length > 0)
        {
            IOrderedEnumerable<int[]> sorted =
                qry.OrderBy(row => row[sortCols[0]]);
            for (int i = 1; i < sortCols.Length; i++)
            {
                int col = sortCols[i]; // for capture
                sorted = sorted.ThenBy(row => row[col]);
            }
            qry = sorted;
        }

        // show results (does actual sort when we enumerate)
        foreach (int[] row in qry)
        {
            foreach (int cell in row)
            {
                Console.Write(cell);
                Console.Write('\t');
            }
            Console.WriteLine();
        }
    }
}

You could also (alternatively) build a comparison to pass to Array.Sort.

Marc Gravell
I updated your answer to have the for loop start at 1 instead of 0. Otherwise you order by the first column twice, which doesn't add a lot of extra functionality ;)
Ronald Wildenberg
@rwwilden - thanks; I switched approach half way through, and forgot to fix that bit; cheers.
Marc Gravell
Marc, rwwilden - thank you very much. That is exactly what I wanted.I think I get stuck with OrderBy and forgot about ThenBy.Problem solved.
Ildar
shahkalpesh
shahkalpesh: I'm worry about efficiency. The rank and indices in this multidimensional array can be very big. It is interesting which way in this case is faster: LINQ, SQL or C#?
Ildar
DataTable != SQL; I don't think anyone is suggesting pushing the data down to a db just to sort it. "faster" would need profiling - but note that DataTable is actually arranged by column (not by row), so sorting *might* be more expensive with a DataTable (untested, but makes sense). I would expect the Array.Sort and LINQ approaches to be similar, with LINQ "good enough" to be worth the extra simplicity.
Marc Gravell
Way this doesn't work:IOrderedEnumerable<uint[]> sorted = from row in qry from col in sortCols orderby row[col] select row; It is not sorting but mixing up data.
Ildar
Can you clarify how you are using that? In particular, the query syntax usage (from ... select) won't allow you to append sorts (ThenBy) at runtime; I expect this is part of the issue, but I'd need to see how you are trying to use it to be sure.
Marc Gravell
Marc: I was trying to use OrderBy only without ThenBy. In a regular way it is posible to put a sequence of items to sort by: OrderBy row.Name, row.LastName,...I am trying to find out how to dynamically list this sequence to OrderBy. This query doesn't give a error but it doesn't work:IOrderedEnumerable<uint[]> sorted = from row in qry from col in sortCols orderby row[col] select row;
Ildar
Query syntax will work, but not for a dynamic number of columns - you need to ThenBy the subsequent columns. The "orderby row[col] select row" should work fine for a *single* sort, though - is it not? Or are you seeing some error?
Marc Gravell