1

I have a multidimentional array

array = [];
array[0] = [1,3,8,4,9,5];
array[1] = [5,9,4,2,9,3,0];
array[2] = [5,2,6,1,3,8,4,9,5,17,2,9,3,0];
array[3] = [-1,0,20,6];

I want to sort it to get this result

[
       [-1,0,0,0,1,1],
       [2,2,2,3,3,3,3],
       [4,4,4,5,5,5,5,6,6,8,8,9,9,9],
       [9,9,17,20]
]

I have defined this function that helped me get this result

Array.prototype.sort_multi = function()
{
    var arr = [];
    this.forEach(function(element_arr,index_arr,array_arr)
    {
        element_arr.forEach(function(element,index,array)
        {
            arr.push(element);
        });
    });
    arr.sort(function (a, b) { return a - b;});
    this.forEach(function(element_arr,index_arr,array_arr)
    {
        element_arr.forEach(function(element,index,array)
        {
            array_arr[index_arr][index] = arr.shift();
        });
    });
    return this;
}

My question is: is there a simple way to do this ? for example using the function sort, or a simple algorithm ... ?

1
  • 1
    Join it, sort it, chunk it into pieces of the original size Commented Jul 26, 2014 at 15:50

1 Answer 1

4

A slightly simplified (and slightly more efficient) version of sort_multi():

Basically what is happening here is:

  1. The items in the original array are combined into one big array (for easy sorting)
  2. We record the lengths of the original child arrays while joining
  3. Sort the joined array numerically (as in the code you posted)
  4. Split the sorted big array as per the lengths of the original child arrays
  5. Return the result

Why this is more efficient than the original code:

  1. The original code iterates through each child array element by element for joining. This is not needed since we have the natively implemented concat() for exactly that.
  2. The original code again iterates element by element when splitting the joined/sorted array - Not needed since we have splice().

Array.prototype.sort_multi = function() {
    var joined = [], lens = [], result = [];
    this.forEach(function(item) {
        joined = joined.concat(item);
        lens.push(item.length); // store the initial lengths
    });
    joined = joined.sort(function (a, b) { return a - b;}); // sort numerically
    lens.forEach(function(item) { // for each length in lens
        result.push(joined.splice(0, item));
    });
    return result;
}
Sign up to request clarification or add additional context in comments.

6 Comments

Actually, your code with the repeated concats and splices is much less efficient than the original code. Can you fix that?
@Bergi - How is it less efficient.. It concats once for each child array and splices once for each child array expected in the output. So if you have 4 child arrays, it concats 4 times and splices 4 times. Can it be reduced? [Note: The method is to be called only on the parent array containing child arrays]
Exactly. For 4 lists in the array, you create 4 joined arrays, and then do 4 splices, where each of these operations needs to iterate the whole array. It has O(n*n*m) complexity while it could be O(n*m)
Can you please post the suggested improvement in a fiddle perhaps. Maybe even as an answer as it will be helpful to future visitors. I'm out of ideas as to how to reduce it further.
Ok, concat can take any number of params, so one call should suffice. Still we'll need 4 splices. Right?
|

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.