Merging the elements of nested arrays into one big array - javascript

I'm trying to merge the elements of the array into one big array. But I receive a message saying:
ReferenceError: reduce is not defined
Here is my code:
var arrays = [[1, 2, 3], [4, 5], [6]];
console.log(reduce(arrays, function(arrayOne, arrayTwo){
return arrayOne.concat(arrayTwo);
}, 0));

reduce() is a method of the Array object, so you must use arrays.reduce().
Moreover, since your initial value is set to 0 (the 2nd parameter), you can't use arrayOne.concat on it, since it's not an array, so you must set the initial value to [].
var arrays = [[1, 2, 3], [4, 5], [6]];
console.log(arrays.reduce(function(arrayOne, arrayTwo){
return arrayOne.concat(arrayTwo);
}, []));
Note that calling Array.flat is easier:
var arrays = [[1, 2, 3], [4, 5], [6]];
// If you expect a multi-level nested array, you should increase the depth.
var depth = 1;
console.log(arrays.flat(depth));

reduce() is only defined on Arrays, you cannot call it by itself:
arrays.reduce(
function (a, b) { return a.concat(b); }
);
// Array [ 1, 2, 3, 4, 5, 6 ]

Related

How do I apply array methods to individual array that compose a two dimensional array in javascript?

As a two dimensional array is an array of arrays, I needed to apply array methods .unshift() and .pop() to each individual array in a 2D array of my JavaScript code.
Is there a way to do so? I know an individual member can be accessed by looping along a[i][j], but how do I obtain the individual array for applying methods to it?
Example: I have an array:
var a = [
[1,2,3]
[4,5,6]
[7,8,9]
]
Now in the first row I want to remove 3 from last and add 3 to the beginning giving me [3,1,2]. And do the same for all rows.
You can iterate over your array using .forEach(), and then for each element in your array (ie: each inner array), .pop() the last element from the end of your array, and then use .unshift(element) to prepend the element you just popped off you're array:
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
a.forEach(innerArray => {
const last = innerArray.pop();
innerArray.unshift(last);
});
console.log(a);
The above can be implemented using a regular for loop if you find that easier to understand:
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
for(let i = 0; i < a.length; i++) {
const innerArray = a[i];
const last = innerArray.pop();
innerArray.unshift(last);
}
console.log(a);
You can also do this by using .map(), which will produce a new array, leaving your original array a untouched:
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const a_new = a.map(inner => [inner.pop(), ...inner]);
console.log(a_new);
Map it. Functional programming is cool!
// to delete the first and last element of the inner array - `unshift` + `pop`
const result = someArray.map(innerArray => innerArray.slice(1, -1));

How reduce() higher order function works?

Below is reduce() function
function reduce(array, combine, start) {
let current = start;
for (let element of array) {
current = combine(current, element);
}
return current;
}
Now this is the question which i am solving
Use the reduce method in combination with the concat method to “flatten” an array of arrays into a single array that has all the elements of the original arrays.
Here is the solution
let arrays = [[1, 2, 3], [4,5], [6]];
console.log(arrays.reduce((flat,current)=> flat.concat(current), []));
// → [1, 2, 3, 4, 5, 6]
Now if i try this
let arrays = [[1, 2, 3], [4, [79],5], [6]];
console.log(arrays.reduce((flat, current) => flat.concat(current), []));
I get this
[1, 2, 3, 4, [79], 5, 6]
It means that this solution can get a flatten array only up to two nested array
But how it works for this
arrays = [[1, 2, 3], [4,5], [6]];
Because in reduce() function i am using
for( let elements of array) which by the way if i use
It works like this
array = [1,4,6,[6,7],7,6,8,6];
for(element of array)
console.log(element);
// 146[6,7]7686
It does not gets the value from nested array
Then how does it for the first solution
And how to write solution which works for any number of nested array i know it will use recursion but how ?
why this function can only flatten array up to one level deep ?
let arrays = [[1, 2, 3], [4, [79],5], [6]];console.log(arrays.reduce((flat, current) => flat.concat(current), []))
Because the reduce function doesn't know if you are trying to concatenate a primitive (a number) or an array. When the reduce functions tries to concatenate two arrays, it produces a single array, but it doesn't know if every element in the array is a number or an array.
Then, as you suggested, you can use recursion:
function flatten(arrayToFlatten){
return arrayToFlatten.reduce((prev, next)=>{
if(!Array.isArray(next)){ // Base case, when you have a number
return prev.concat(next);
} else { // Recursive case, when you have an array
return prev.concat(flatten(next));
}
}, []);
}
You can do:
const arrays = [[1, 2, 3],[4, [79], 5],[6]];
const getFlatten = array => array.reduce((a, c) => a.concat(Array.isArray(c) ? getFlatten(c) : c), []);
const result = getFlatten(arrays);
console.log(result);

How can I check if a list contains any value from another list?

Using Underscore, I can check if a list contains a single item:
_.contains([1, 2, 3], 3);
Now I want to extend this to check if a list contains any item from another list:
_.contains([1, 2, 3], [4, 1]);
This is what I've got, but is there a neater way?
var isInList = _.some(_.map([1, 2, 3], function(d){ return _.contains([4, 1], d); }));
Use _.intersection function, like this
var isInList = _.intersection([1, 2, 3], [4, 1]).length !== 0;
You probably want _.intersection. This returns the set of elements that appear in both arrays. For example,
_.intersection([1, 2, 3], [4, 1])
> [1]
To turn it into the boolean you're looking for, just check if the returned array is empty.

Is array.slice enough to handle a multidimensional Array in JavaScript?

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).

What is .apply doing in this JavaScript code?

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

Categories

Resources