Compares various methods of JS array merging and their advantages and disadvantages
Original article: Combining JS Arrays
Original Article Date:
Translation Date:
Translated by: Tie
This article is a basic JavaScript skill. We will learn a variety of common methods to combine/merge two JS arrays, and compare the advantages and disadvantages of various methods.
Let's take a look at the specific scenarios:
var q = [ 5, 5, 1, 9, 9, 6, 4, 5, 8];var b = [ "tie", "mao", "csdn", "ren", "fu", "fei" ];
Obviously, the result of simple concatenation of array q and array B is:
[ 5, 5, 1, 9, 9, 6, 4, 5, 8, "tie", "mao", "csdn", "ren", "fu", "fei"]
Concat (...) Method
The most common usage is as follows:
var c = q.concat( b );q; // [5,5,1,9,9,6,4,5,8]b; // ["tie","mao","csdn","ren","fu","fei"];c; // [5,5,1,9,9,6,4,5,8,"tie","mao","csdn","ren","fu","fei"]
As you can see,
CIs a brand new array, indicating
QAnd
BThe combination of the two arrays,
QAnd
BIt's useless now, right?
If
QArray has
10000Elements,
BArrays also have
10000Elements? Then Array
CNow there are 20000 elements. This method consumes 2 times of memory.
"No problem !", You may think that, if q and B are left blank, they will be reclaimed, right? Problem solved!
Q = B = null; // 'Q' and 'B' can be recycled now
Amount? If the array is small, there is no problem, but the memory is limited when large arrays or repeated processing is required, and it needs to be optimized.
Loop insert
OK. Let's add the content of an array to another one.
Array # push ()Method:
// Insert 'B' into array 'q' for (var I = 0; I <B. length; I ++) {q. push (B [I]);} q; // [5, 5, 9, 6, 8, "tie", "mao", "csdn", "ren ", "fu", "fei"] B = null;
Now, q stores the content of two original arrays (q + B ).
It seems that the memory optimization is good.
However, if
QThe array is small and
BHow big is it? For memory and Speed considerations
QInsert
BAbove. No problem, just use
Unshift ()Method substitution
Push ()You can, the corresponding loop traversal also needs to be performed from large to small:
// `q` into `b`:for (var i=q.length-1; i >= 0; i--) { b.unshift( q[i] );}b; // [5,5,1,9,9,6,4,5,8,"tie","mao","csdn","ren","fu","fei"]q = null;
Practical Skills
Sadly, the for loop is very earthy and difficult to maintain. Can we do better?
Let's try it first.
Array # reduce:
// `b` onto `q`:q = b.reduce( function(coll,item){ coll.push( item ); return coll;}, q );q; // [5,5,1,9,9,6,4,5,8,"tie","mao","csdn","ren","fu","fei"]// or `q` into `b`:b = q.reduceRight( function(coll,item){ coll.unshift( item ); return coll;}, b );b; // [5,5,1,9,9,6,4,5,8,"tie","mao","csdn","ren","fu","fei"]
Array # reduce ()And
Array # reduceRight ()Very large, but a little bulky, and the average person cannot remember. JS specification 6
=>Arrow-functions can greatly reduce the amount of Code. However, it is also a waste to execute function calls on each array element.
What about the following code?
// `b` onto `q`:q.push.apply( q, b );q; // [5,5,1,9,9,6,4,5,8,"tie","mao","csdn","ren","fu","fei"]// or `q` into `b`:b.unshift.apply( b, q );b; // [5,5,1,9,9,6,4,5,8,"tie","mao","csdn","ren","fu","fei"]
BIG is higher, right !? Especially
Unshift ()The method does not need to consider the reverse sequence. ES6 expansion operator (spread operator, add
...Prefix) is even higher:
A. push (... B)Or
B. unshift (...)
However, in fact, this method is too optimistic. In both cases, whether it is to pass a or B
Apply ()As the second parameter (when the Function is called using the apply method, the first parameter becomes this internally, that is, context, and scope ).
...In fact, all arrays are split into functions by expanding operators.
Arguments.
The first major problem is that the memory usage doubles (of course, it's temporary !), Because the array needs to be copied to the function stack. In addition, different JS engines have different implementation algorithms, which may limit the number of parameters that can be passed by the function.
If 1 million elements are added to the array, the size of the array must exceed the size allowed by the function stack.
Push ()Or
Unshift ()Call. This method is only available for thousands of elements, so it must be limited to a certain range.
Note:: You can also try
Splice ()He and
Push (..)/unshift (..)They all have the same restrictions.
One option is to continue using this method, but batch processing is adopted:
Function combineInto (q, B) {var len = q. length; for (var I = 0; I <len; I = I + 5000) {// process 5000 pieces of B at a time. unshift. apply (B, q. slice (I, I + 5000 ));}}
And so on. We damage the readability of the Code (or even the performance !). Let's end this journey before we give up.
Summary
Array # concat ()It is a tested method used to combine two or more arrays, but it creates a new array instead of modifying an existing one.
There are many workarounds, but they all have different advantages and disadvantages and need to be selected based on the actual situation.
The advantages/disadvantages listed above, and perhaps the best (including those not listed) method is
Reduce (..)And
ReduceRight (..)
Whatever you choose, you should think about your array merging strategy critically, instead of taking it for granted.