Is sorting or inserting more efficient with concatenating arrays of objects in javascript?

I have several objects with a "num" field. Num can be any number between 1000000000 and 10000000005. I want to make sure that if I have x number of lists, all the lists should be concatenated into array1 in ascending sorted order depending on the num property.

If I start with an array like this "

array1": [{item:23532532, num:1000000520},{item:23523, num:1000000620},{item:346346432, num:1000000620}]

      

I have a second array

"array2": [{item:23532, num:....},{item:3623, num:....}]

      

Assuming array2 is in ordered order with "num", is this more efficient:

1) Add Then Sort Whole - Loop through each element in "array2" and add it to the end of "array1" and then create javascript in "sort" function "num" on the whole array?

2) Paste where you want - Skip each element in "array2" and use "if" conditions to check if the value of "num" is greater than the current element in "array2", if so, then insert the element before this index through " splice". (Doesn't use javascript's native array sort)

Or is there a better method? Pseudo code or sample code is a plus.

+3


source to share


3 answers


I have measured the results of three different algorithms in three different browsers.

In all performance-related questions, there are two things:

  • If you really want to know the answer, you have to test your specific algorithm across multiple browsers to actually answer the question.

  • Many of the performance issues are actually not material in the given context in which they are used, so worrying about them until you know you need to worry about them is nothing more than wasted time about premature optimization or even unnecessary optimization. Therefore, before working on a specific area of ​​performance, you should know that it is important and know that it is worth investing the time.

However, here are some measurements for the three algorithms. This assumes that you start with two arrays of objects, each sorted independently by one specific numeric property that is present in each object.

Here's the jsperf: http://jsperf.com/concat-sort-vs-insert-sort/5 , which has code for each of the three algorithms.

Algorithm 1 is concatenated and then sorts the concatenated array. In JS, this is nothing more:

var result = arr1.concat(arr2);
result.sort(sortByNum);

      

Algorithm 2 - Attempt to sort the insert. The basic idea is to iterate over the second array and, for each element in that array, find where to insert it into the first array. Since both arrays are sorted, we only need to look for a place to insert the next element into the first array at the position after we inserted the last element.



Algorithm 3 is merge sort. The idea here is that you create an empty results array and two indices, one for each of the two original arrays. For the value at each source index, you insert the result at the lower of the two elements and then increment the source index. Whenever the original index is exhausted, you push the rest of the other array. I assumed it would be more efficient than insertion sort because it doesn't need to insert elements in the middle of the array, just add to the end, which will likely speed things up.


To run the test, I created two arrays, each containing 100 objects. Each object has a numeric property that is assigned a random number between 0 and 100,000. Then, each of the two source arrays is pre-sorted. Then each algorithm is tested against these two original arrays.

And here are the results:

enter image description here

Here's the code for the merge sort algorithm:

function mergeSort(arr1, arr2) {
    var result = [];
    var index1 = 0;
    var index2 = 0;
    if (!arr1.length) {
        return arr2.slice(0);
    } else if (!arr2.length) {
        return arr1.slice(0);
    }
    while (true) {
        if (arr1[index1].num <= arr2[index2].num) {
            result.push(arr1[index1]);
            ++index1;
            // see if we reached the end of the array
            if (index1 >= arr1.length) {
                result.push.apply(result, arr2.slice(index2));
                break;
            }
        } else {
            result.push(arr2[index2]);
            ++index2;
            // see if we reached the end of the array
            if (index2 >= arr2.length) {
                result.push.apply(result, arr1.slice(index1));
                break;
            }
        }
    }
    return result;
}

      

Working demo: http://jsfiddle.net/jfriend00/mja1c13d/

+4


source


The built-in sort is likely to be significantly more efficient than writing your own insertion sort in most cases . If this were not the case, then the native Array.sort()

would have been written to do it myself.

However, you may look at one of the exceptions, depending on the size of the two arrays. If you know that one of the two arrays is already sorted, and the other (unsorted) array is short, AND the total size of the two arrays is large, then iterating through the short array and inserting into the large, sorted one may be more efficient.



The insertion (if you know one list is already sorted) will be in order N1 * N2

; concatenation and sorting is probably something like (N1 + N2) log (N1 + N2)

. Depending on these two relative sizes, it can go anyway.

But if your lists are not very large, the difference will be below the human-readable threshold, so maintaining consistency proves "concatenation and sorting". Actual real performance measurements. Trump guesses are always and performance is highly data-specific. So if you are really concerned, write and test them using real data.

+3


source


While I don't think this will fit your data perfectly and therefore probably won't be useful to you, it's worth mentioning that sorting counting is done in linear time. If you knew in advance that you need to sort integers without spaces in the data, so that an object exists for every integer from 1,000,000,000 to 1,000,000,0005, and all integers are unique, you can use this by doing a mathematical calculation to reduce 1,000,000,000 to zero point , 1000000001 to position 1 and so on, you get there by subtracting 1,000,000,000 from each number to get the index in the zero-valued array.

You end up with something like

var array = new Array(9000000005); //10000000005 - 1000000000
var obj = {"item":23532532, "num":1000000520};
var array[1000000520 - 1000000000] = obj; //goes into index 520

      

The subtraction operation brings your linear time complexity to 2n instead of n. Javascript-built sorting is probably n log n time complexity. 0 to 100 on a plot of xy n log n coordinates is better, but at x> 100 2n scales forward in performance. For 9 billion items, however this is unrealistic, this is valid for Javascript, you can see that the time difference will be greatly improved.

It is difficult to fix the scale of this graph, but it gives a good idea of ​​the comparison ... y=x

is a sort, y=2x

represents a sort of count with a subtraction operation. y = x log x

is most likely a built-in Javascript array sort.

enter image description here

+2


source







All Articles