both javascript code accomplish the same task merge the second array into the first one, i have read various blogs etc claming Option 2 is more memory efficient,
Is there a way or a tool to verify and see it for myself the memory usage in the Option 2 is lower ?
Option 1
//consume a lot of memory
var array1 = [1, 2, 3];
var array2 = [4, 5, 6];
console.log(array1.concat(array2));
Option 2
//reduce the memory usage
var array1 = [1, 2, 3];
var array2 = [4, 5, 6];
console.log(array1.push.apply(array1, array2));
i tried this approach https://www.valentinog.com/blog/node-usage/ node js code, not much helpful
also tried https://github.com/paulirish/memory-stats.js dosent seems to work
Your premise is wrong. Both scripts do not accomplish the same task.
Your first option allocates a new result array with 6 elements, and leaves both array1 and array2 untouched. (See the documentation for Array.prototype.concat().)
var array1 = [1, 2, 3];
var array2 = [4, 5, 6];
console.log(array1.concat(array2)); // [1, 2, 3, 4, 5, 6]
console.log(array1); // [1, 2, 3]
console.log(array2); // [4, 5, 6]
Your second option merges the contents of array2 into array1. (See the documentation for Array.prototype.push().)
var array1 = [1, 2, 3];
var array2 = [4, 5, 6];
console.log(array1.push.apply(array1, array2)); // 6
console.log(array1); // [1, 2, 3, 4, 5, 6]
console.log(array2); // [4, 5, 6]
So the second option only requires a total of 9 array elements, while the first option requires 12. On a language level, option 2 is 25% more memory-efficient. How much memory is actually used by the JavaScript engine you're using is an implementation detail. In addition, contrived examples like these are typically not good candidates for reliable performance testing as the engine's JavaScript interpreter might apply various optimizations.
Related
Scenario 1:
var myArray = [2, 3, 4, 5];
function doStuff(arr) {
arr = [];
}
doStuff(myArray);
console.log(myArray); // [2,3,4,5]
Scenario 2:
var myArray = [2, 3, 4, 5];
function doStuff(arr) {
arr.pop();
}
doStuff(myArray);
console.log(myArray); // [2,3,4]
Why does scenario 1 not update the globally declared array but scenario 2 does?
In the first example:
You are altering the variable arr which is merely just holding a reference to the array [2, 3, 4, 5], so instead of holding a reference to [2, 3, 4, 5], it will hold a reference to another array [].
At the line var myArray = [2, 3, 4, 5];:
myArray -----------------------------------> [2, 3, 4, 5]
Then at the line doStuff(myArray);:
myArray -----------------------------------> [2, 3, 4, 5]
↑
arr ----------------------------------------------/
Then at the line arr = [];:
myArray -----------------------------------> [2, 3, 4, 5]
arr ---------------------------------------> []
=> So, after the call to doStuff, myArray is still [2, 3, 4, 5].
In the second example:
You are using the reference to [2, 3, 4, 5] stored in arr to call a function pop on it that alters it.
At the line var myArray = [2, 3, 4, 5];:
myArray -----------------------------------> [2, 3, 4, 5]
Then at the line doStuff(myArray);:
myArray -----------------------------------> [2, 3, 4, 5]
↑
arr ----------------------------------------------/
Then at the line arr.pop();:
myArray -----------------------------------> [2, 3, 4, 5].pop()
↑
arr.pop() ----------------------------------------/
Which alters the array to:
myArray -----------------------------------> [2, 3, 4]
↑
arr ----------------------------------------------/
=> So, after the call to doStuff, myArray is now [2, 3, 4].
In the first case you are doing a new memory allocation while you are actually modifying the array in the second case.
Hence in the first case the value does not get modified.
For eg:
var myArrayOne = [2, 3, 4, 5];
function doStuff(arr) {
arr = [7,8,9]; //assigining a whole new object to the copy
}
doStuff(myArrayOne);
console.log(myArrayOne); // [2,3,4,5]
// Scenario 2
var myArrayTwo = [2, 3, 4, 5];
function doStuff(arr) {
arr.pop(); //modifying the internals of the arr object
}
doStuff(myArrayTwo);
console.log(myArrayTwo); // [2,3,4]
arr is a reference to the array, which exists somewhere in memory (you don't know where, and you don't care). When you say arr = [], you're creating a new array somewhere in memory, and changing arr to refer to that new array. The old array still exists in memory. If there was nothing referring to the old array then it would eventually be garbage collected, but in this case it's still referred to by myArray so it remains untouched.
arr.pop() on the other hand is modifying the array, not changing references.
In the first function, you're just reassigning the parameter of the function. That has no effect on the passed data.
In the second, you're actually mutating the passed array via the call to pop.
Think of it this way: in
var a = 1
a = 2
Is the 1 modified in any way? No, the reference a that was pointing to it was just changed.
I recently ran into the problem where I would like to select multiple elements from an array, to return a sub-array. For example, given the array:
a = [1, 5, 1, 6, 2, 3, 7, 8, 3]
And the index array of:
i = [3, 5, 6]
I want to select all elements in a, who's index appears in i. So the output in my simple example would be:
[6, 3, 7]
I completely realise I could use a for loop over i and construct a new array then use Array.push(a[index (in i)]) to add in each, but I was wondering if there was a clearer/cleaner way to achieve this (possibly using underscore.js, or something similar).
i.map(function(x) { return a[x]; })
// => [6, 3, 7]
You can try this
a = [1, 5, 1, 6, 2, 3, 7, 8, 3];
i = [3,5,6];
var res= []; //for show result array
for (var n in a){ //loop a[]
for(var index in i){ //loop i[]
if( n == i[index] ) //n is index of a[]
res.push(a[n]); //add array if equal n index and i[] value
}
}
alert(res); // 6,3,7
You could use map function to achieve your desired result.
var a = [1, 5, 1, 6, 2, 3, 7, 8, 3];
var i = [3, 5, 6];
var mapped = i.map(function(index) {
return a[index];
});
console.log(mapped);
Here is the working jsfiddle.
However with above example, map not be available in all browsers yet. Here is the quote from documentation of map.
map was added to the ECMA-262 standard in the 5th edition; as such it
may not be present in all implementations of the standard.
If your code will be running in old browsers then you will need to add a polyfill. However there are libraries that give you similar functionality with polyfills for older browsers. Along with map function, underscodejs has tons of other helpful functions. I higly recommend you to look at what underscorejs has to offer. It provides tons of helper functions and has quite wide range browser support.
You would do following in underscorejs and wont have to worry if your code works in cross browsers.
var a = [1, 5, 1, 6, 2, 3, 7, 8, 3];
var mapped = _.map([3, 5, 6], function(index) {
return a[index];
});
alert(mapped);
Here is jsfiddle for that.
Is array.slice enough to clone a multidimensional Array in JavaScript?
For example:
var array = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
var b = array.slice();
console.log(b);
I saw a secondary implementation as this from Play by Play: Lea Verou on pluralsight:
b = array.slice().map( function(row){ return row.slice(); });
The docs are pretty clear:
The slice() method returns a shallow copy of a portion of an array into a new array object.
So the answer is no: slice by itself is not enough to clone a multidimensional array. It will only clone one dimension. You need to recursively clone each element (the way the "secondary implementation" you posted is doing) if you want a deep clone.
From MDN:
The slice() method returns a shallow copy of a portion of an array into a new array object.
That is, it will not clone the internal arrays / objects. Observe:
var array = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
var b = array.slice();
b[0].push(10);
console.log(array);
> [ [1, 2, 3, 10], [4, 5, 6], [7, 8, 9] ]
So if you want a deep copy of your 2D array, then you'd have to go with the map method (or something similar).
I am doing the Netflix tutorial on Reactive Programming and I came across this piece of code that I don't fully understand.
Array.prototype.mergeAll = function() {
var results = [];
this.forEach(function(subArray) {
results.push.apply(results, subArray);
});
return results;
};
Why use apply in this line of code results.push.apply(results, subArray);? Why not just use results.push(subArray)? What is the difference in the code?
The results wouldn't be the same at all. You can test this for yourself:
results = [1, 2, 3];
subArray = [4, 5, 6];
results.push(subArray);
console.log("With push:", results); // With push: [1, 2, 3, [4, 5, 6]]
results = [1, 2, 3]; // reset results
results.push.apply(results, subArray);
console.log("With apply:", results); // With apply: [1, 2, 3, 4, 5, 6]
apply accepts an array of arguments, and the elements of the array become individual arguments to the function.
This lets you invoke the function push with an arbitrary number of arguments, where each argument is added to the array. Simply calling results.push(...) would invoke the function with a single argument, which would be an array, resulting in the entire subArray being pushed onto results as one element.
In the above example, results.push.apply(results, subArray) is equivalent to calling results.push(4, 5, 6), while results.push(subArray) simply invokes results.push([4, 5, 6]).
The net effect of using one over the other is that, given an input array containing sub-arrays...
[[1, 2, 3], [4, 5, 6], [7, 8], [9]]
... using results.push would produce an identical array, where each sub-array was pushed onto results as a single element:
[[1, 2, 3], [4, 5, 6], [7, 8], [9]]
Using results.push.apply would cause each element from each sub-array to be pushed onto results as its own element, resulting in the desired flattened array:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Example 1:
var results = [];
results.push.apply(results,[2,3,4])
results [2,3,4]
Example 2:
var results2 = [];
[].push.apply(results2,[2,3,4])
// results2 [2,3,4]
results.push.apply is identical to [].push.apply. Both of them represent array's push method.
the first parameter in apply() method : results / results2, representing the scope/this inside Array.prototype.push method.
Here is the link giving a good example, how the first parameter in apply() method works.
If you want to know, why the second parameter of apply() method is array of arguments. This link's example has good explanation.
Basically
[].push.apply(results2,[2,3,4])
// results2 [2, 3, 4]
result2.push(2,3,4)
// results2 [2, 3, 4]
The first method is equal to the second method
Looking for a function in underscore.js that will take 2 arrays and return a new array of unique values? Something like _without
_.without([0, 1, 3, 9], [1, 3]);
I would like => [0,9] returned
It appears _without's 2nd arg is a list of values, not an array. Anyone out there know
if underscore has the specific function I'm looking for? Or can I take an exisitng array and covert it to values the function expects.
Thanks,
~ck in San Diego
The _.difference function should give you what you're looking for:
_.difference([0, 1, 3, 9], [1, 3]); // => [0, 9]
_.without.apply(_, [arr1].concat(arr2))
[[0, 1, 3, 9]].concat([1, 3]) is [[0, 1, 3, 9], 1, 3];
_.without.apply(_, [[0, 1, 3, 9], 1, 3]) is _.without([0, 1, 3, 9], 1, 3)
You've got a perfectly good _.without method. So just convert an array into a list of values you can pass into a function. This is the purpose of Function.prototype.apply
var result = _.reject([0, 1, 3, 9], function(num) {
return _.include([1, 3], num);
});
Lo-Dash is extended Underscore and here is what you need: http://lodash.com/docs#xor
_.xor
Creates an array that is the symmetric difference of the provided arrays. See http://en.wikipedia.org/wiki/Symmetric_difference.
_.xor([1, 2, 3], [5, 2, 1, 4]);
// → [3, 5, 4]