1

I've done some extensive searching for this so if this is a duplicate please slaughter me :D

I have a List of byte arrays (List) where the arrays are of varying length. I need to sort the list by the array lengths in ascending order then by the bytes in the array (please see example).

Example:

I want to go from:

{0,1,2}
{0,4}
{0,3,2}
{0,1,3}
{0,2,4,6,1}
{0,1,1}
{0,3,4,5}

to:

{0,4}
{0,1,1}
{0,1,2}
{0,1,3}
{0,3,2}
{0,3,4,5}
{0,2,4,6,1}

It's essentially alphabetical order but with a set of numbers instead of characters (arguably the same thing), any ideas?

1
  • 2
    Write a custom comparer. Commented Feb 14, 2015 at 17:12

2 Answers 2

9

The only thing you need to do is implement a IComparer<T> interface and provide that to the sorting algorithm. In this case the algorithm looks like:

public ByteArrayComparer : IComparer<byte[]> {

    public int Compare (byte[] ba, byte[] bb) {
        int n = ba.Length;  //fetch the length of the first array
        int ci = n.CompareTo(bb.Length); //compare to the second
        if(ci != 0) { //if not equal return the compare result
            return ci;
        } else { //else elementwise comparer
            for(int i = 0; i < n; i++) {
                if(ba[i] != bb[i]) { //if not equal element, return compare result
                    return ba[i].CompareTo(bb[i]);
                }
            }
            return 0; //if all equal, return 0
        }
    }

}

Next you can use the List<T>.Sort method:

List<byte[]> data = new List<byte[]>();
//add arrays to data
data.Sort(new ByteArrayComparer());
//data is now sorted

The sorting algorithm requires that the comparator is valid, a comparator is valid if it satisfies the three constraints on an ordering relation:

  1. Reflexivity: if an elements is compared with itself, return 0;
  2. Anti-symmetric: If x is smaller than y (return something less than 0), then y is greater than x (something greater than 0);
  3. Transitive: if x is smaller than y and y is smaller than z, then x is smaller than z.

If the comparer doesn't satisfy that relation, the sorting algorithm will fail to sort correctly, simply because your order makes no sense.

Sign up to request clarification or add additional context in comments.

Comments

2

Why not simply use LINQ

MyList = MyList.OrderBy(arr=>arr.Length).ThenBy(arr =>arr.Sum()).ToList();

A working example :

   List<int[]> a = new List<int[]>();

   int[] t1 = { 0, 4 };
   int[] t2 = { 0, 1, 2 };
   int[] t3 = { 0, 1, 3 };
   int[] t4 = { 0, 2, 4, 6, 1 };
   int[] t5 = { 0, 1, 1 };
   int[] t6 = { 0, 3, 4, 5 };

   a.Add(t1);
   a.Add(t2);
   a.Add(t3);
   a.Add(t4);
   a.Add(t5);
   a.Add(t6);

   a = a.OrderBy(arr=>arr.Length).ThenBy(arr =>arr.Sum()).ToList();

    foreach (int[] item in a)
    {
        foreach (int item2 in item)
        {
             Console.Write(" "+item2);
      }
      Console.WriteLine();
   }

Sample output :

0 4
0 1
0 1 2
0 1 3
0 3 4 5
0 2 4 6 1

And as pointed out this could fail in scenarios like {3 4 5} , {4 5 3}

2 Comments

I didn't dv, but I think it's still incorrect. I think the OP wants to sort lexicographically. So that {1,200} is less than {3,5} because the first element is smaller. If not look to the second and so on...
What's first? {0,3,4,5} or {0,3,5,4} ?

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.