1

I'm trying to sort the following List List<char[]> permutations = new List<char[]>();

it contains all the permutations of the number 0,1,2,3,4,5,6,7,8,9 however they are not sorted but I need them sorted. This is what I did to fix my problem :

        permutations = permutations.OrderBy(arr1 => arr1[9]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[8]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[7]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[6]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[5]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[4]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[3]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[2]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[1]).ToList();
        permutations = permutations.OrderBy(arr1 => arr1[0]).ToList();

how can I avoid this or how can this be written in 1 line ?

KOPEUE
  • 260
  • 4
  • 15

3 Answers3

3

First I would note that you are re-sorting the list 9 times.

The proper way to chain orderings is to use ThenBy (note that the order of comparisons is reversed to get the results to order in the same manner that you have now):

    permutations = permutations.OrderBy(arr1 => arr1[0])
                               .ThenBy(arr1 => arr1[1])
                               .ThenBy(arr1 => arr1[2])
                               .ThenBy(arr1 => arr1[3])
                               .ThenBy(arr1 => arr1[4])
                               .ThenBy(arr1 => arr1[5])
                               .ThenBy(arr1 => arr1[6])
                               .ThenBy(arr1 => arr1[7])
                               .ThenBy(arr1 => arr1[8])
                               .ThenBy(arr1 => arr1[9]).ToList();

One simple way to reduce the amount of code is

permutations = permutations.OrderBy(a => new string(a)).ToList();

Or to just order the list in-place.

permutations.Sort((a1, a2) => (new string(a)).CompareTo(new string(a2)));

Granted those generate a lot of strings, but the next best option is to write an IComparer<char[]> that compares two character arrays the way you want it to. One other option (since I know that the list of character arrays came from a different question) would by so store the permutations as strings instead of arrays. Then sorting is a no-brainer:

permutations.Sort();
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • Great answer. Just a few notes : OrderBy(a => new string(a)).ToList() && .Sort((a1, a2) => (new string(a1)).CompareTo(new string(a2))); are really slow in performence compared to the .ThenBy method,also the permutations.Sort(); wont work if we are using chars since we don't provide IComparer to it. The first one is almost 4 times faster than the second and the third – KOPEUE Apr 06 '16 at 22:15
  • 1
    1) That's why I said it was a way to reduce _code_. I'm not surprised it's slower just because of the amount of memory allocated for those strings. Whether or not that's a _problem_ depends on the overall performance of the system. – D Stanley Apr 06 '16 at 22:20
  • 1
    2) If you stored strings instead of character arrays then you wouldn't need to pass a comparer to `Sort` - it will sort the strings alphabetically be default. It doesn't work for character arrays since there's not a "default" comparer for char arrays. – D Stanley Apr 06 '16 at 22:21
  • nice, the original way could be simplified using a foreach: instead of 10 lines......var order = permutations.OrderBy(e=> e[0]); for (int i = 1; i < 9; i++) order = order.ThenBy(e=> e[i]); var final = order.ToList(); just need to fix the closure :P – George Apr 06 '16 at 22:23
  • i will be captured this way (closure) so it will look like this ` var order = permutations.OrderBy(e => e[0]); for (int i = 1; i < 9; i++) { var i1 = i; order = order.ThenBy(e => e[i1]); } var final = order.ToList();` – KOPEUE Apr 06 '16 at 22:25
  • @KOPEUE I would see how much faster it is to store the permutations as strings instead of char arrays - I bet it's faster _and_ cleaner. – D Stanley Apr 06 '16 at 22:26
1

This is pretty old but I was working on this and have a solution that is suggested in comments but not shown. As suggested by George, the dynamic way to handle this is to use a for loop but there is one gotcha as noted here OrderBy / ThenBy in Loop.

This is much faster than converting each char[] to a string as noted in the other comments and answers.

var p = permutations.OrderBy(x => x[0]);
for (int i = 1; i < s.Length; i++)
{
    var index = i; //Must do this to Avoid Gotcha
    p = p.ThenBy(x => x[index]);
}
permutations = p.ToList();
AsherVitek
  • 21
  • 2
0

Just use string instead of char[] which is basically IEnumerable<char> In this way you can simply write

permutations.Sort();

if you want to keep it your way you can chain your expressions like:

permutations = permutations.OrderBy(arr1 => arr1[9])
    .ThenBy(arr1 => arr1[8])
    .ThenBy(arr1 => arr1[7])
    .ThenBy(arr1 => arr1[6])
    .ThenBy(arr1 => arr1[5])
    .ThenBy(arr1 => arr1[4])
    .ThenBy(arr1 => arr1[3])
    .ThenBy(arr1 => arr1[2])
    .ThenBy(arr1 => arr1[1])
    .ThenBy(arr1 => arr1[0])
    .ToList();
Adassko
  • 5,201
  • 20
  • 37