Javascript: pushing an array into an array - javascript

JS question:
I need to push an array to be an element in another array. I got 2 ways: a plain push() and one the same but with spread operator
arr.push([newArr]);
arr.push([...newArr]);
(both arr and newArr are arrays)
What does the spread operator actually accomplishes here?
Observing in the console, in the 2nd example, I get the results I want:
res[0]
(3) [1, 2, 3]
So the array I pushed becomes an element in the new array. so far so good.
But in the 1st example, without the spread operator, I get:
res[0]
[Array(3)]
res[0][0]
(3) [1, 2, 3]
And this is what I don't understand. why, when not using spread, I get what seems to be like... sort of a wrapper... over the array? what does it even mean, when I get [Array(x)] in the console?? is it array within array or...?
so the question is: what is this [Array(x)], why is is there, and why does the spread operator clears it out?
Thank You!

Let's take a look at this example
const newArr = [1,2,3];
const a1 = [newArr];
const a2 = [...newArr];
console.log(a1);
console.log(a2);
In the first case, newArr becomes the first element of the array a1.
In the second case, spread operator takes all the elements of the newArr and put them one by one as elements of the array a2.
So a1==[newArr], a2==[newArr[0], newArr[1], newArr[2]]

Consider your array arr as a row of lockers.
When you use arr.push([newArr]); you're taking that entire array [newArr], and putting the entire thing into the next available locker. If newArr contains 3 values (lockers) of its own, all three go into that next, single available locker in arr as newArr, expanding the arr array to accommodate the site, in this case adding 1 locker.
When you use the spread operator, arr.push([...newArr]);, you're taking each of the elements of newArr out of newArr, and putting each one in turn into the next available locker in the row. If newArr has 3 values (lockers) of its own, the first goes into the next available locker in arr, the 2nd into the 2nd available locker in arr, and the 3rd into the 3rd, expanding the arr array to accommodate the site, in this case adding 3 lockers.
The spread operator essentially flattens the array, whereas push does not.

arr.push([newArr]); pushes an array with one item newArr into arr.
arr.push([...newArr]); pushes a shallow copy of newArr into arr.
Spread syntax.

Related

Have trouble doing push to a sub-array in a 2D JS array

Suppose I made a 5 by 2 matrix populated by integer 9
let arr = Array(5).fill(Array(2).fill(9));
Now I want to push integer 8 into the fourth line of the matrix by doing
arr[3].push(8);
I ended up getting [[9,9,8],[9,9,8],[9,9,8],[9,9,8],[9,9,8]]. All lines in the matrix have been pushed 8.
Why?
I found out if I did things like below, I got what I wanted, but why?
arr[3] = [...arr[3]];
arr[3].push(8);
Short Answer: This is because all 5 arrays are sharing a reference to the exact same array
i.e. Array(2).fill(9) => [9,9]
Quick Solution: Use Array.form to create a deep-copy for each layer
let arr = Array.from({length: 5}, e => Array(2).fill(9));
or try any other solution from these answers (ref 1, ref 2, ref 3)
See the working solution below (notice the shallow copy in the console)
// PROBLEM
// Shallow-copies
let arr1 = Array(5).fill([...Array(2).fill(9)]);
arr1[3].push(8);
// writing to the document
document.write('Shallow -> ', arr1)
// loggin in console
console.log('shallow ', arr1)
// SOLUTION
// deep-copies
let arr2 = Array.from({length: 5}, e => Array(2).fill(9));
arr2[3].push(8);
// writing to the document
document.write('<br><br> Deep -> ', arr2)
// loggin in console
console.log('deep', arr2)
Details: As mentioned in the documentation here (5th point in Description here) about the first parameter of .fill which is the array you are passing in i.e. [9,9]
If the first parameter is an object, each slot in the array will reference that object.
Exact scenario is mentioned inside the documentation as well, see this code snippet here
This shows that all the items are basically a reference to the same object [also known as shallow copy], altering one item will result in the same changes in every other item.
Array.from fixed this issue as Array(2).fill(9) will now create a new array on every element of the array. Learn more about Array.from here
This fix you mentioned at the end is working because by using spread operator [...arr[3]] we are creating a deep copy of this [9,9] array on the 4th index, which is not a reference to that same initial array [9,9] anymore so, now changing this item at 4th index will only change the 4th item's array itself.
Note This spread operator ...arr is only creating a single level deep copy so, if (supposedly) this arr[3] contains another multi-level array inside it, then only the first level will be created as a deep copy and all the inner ones will remain as shallow copies [i.e. same reference to the object]

How can you change the index of multiple array objects?

Problem:
How can you change the index of multiple objects within an array of 100 objects?
In my case I would like to push them to the end of the array.
I have fetched a json array that contains over 100 objects, each with their own properties including a number property for each object that can be used to filter.
Attempts
I tried populating a variable using .splice to remove the specific array objects. Although .push wont accept that variable.
Also tried .slice but couldn't push the sliced objects to the end.
Also tried to loop through the original array using a for loop and an if statement with the condition of each objects "number" property.
Code:
(the fetch is a success, only issue is the restructure of the array itself)
elementsArray.value = await data.json();
let removedElements = elementsArray.value.slice(56,71);
elementsArray.value.push(removedElements);
With slice, the original array will not be modified. Use splice instead.
push accepts one or more elements. so use spread syntax
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant']
const removedElements = animals.splice(2, 2)
animals.push(...removedElements)
// some other alternatives
// Array.prototype.push.apply(animals, removedElements)
// animals.concat(removedElements)
console.log(animals)
Here is a way you can use splice to append a to b but as in the commentarys mentioned for this use case .concat() or .push(...otherArray) is the better choice
let a = [1,2,3],
b = [4,5,6];
a.splice(0, 0, ...b);
console.log(a);

Adding two arrays with existing and repeated memebers of two arrays replacing the repeated ones

I'm in a situation in which for me it is vital to add two arrays together and create a new array which does not have the memebers of tow arrays which are the same being added to the final array as multiple members but rather just one,I just want to have one memeber as the representive of those identical members from two arrays in the final array, not having them as multiple memebers in the final array,I tried concat() and it did exactly what I don't want.
How can I do this, guys?
like:
let arrayone = [2,4,6];
let arraytwo = [2,4,7];
I want the final array to be
finalarray = [2,4,6,7]
but concat() gives me
final array [2,4,6,2,4,7]
This was just for more clarification, the members of my arrays are objects.
In set theory, this is called the "union". There are a number of ways to do this in JavaScript. If the arrays only contain primitive values, you can simply build a Set out of them, and then spread back into an array:
const firstArray = [1, 2, 3]
const secondArray = [3, 4, 5]
const union = [...new Set([...firstArray, ...secondArray])] // [1, 2, 3, 4, 5]
The Set constructor ensures that no duplicate values are added to the set. If the values of the arrays are NOT primitives (i.e. objects or something else), you'll need to use some other means of iteration to achieve a union. Here is a good example of deriving the union of two arrays of objects.

Why doesn't array.splice() work when the array has only 1 element?

Is this intended behavior? I would expect an empty array to be returned here.
JavaScript
let arr = [1];
console.log(arr.splice(0, 1))
Console
1
Because it returns what was removed, which is [1] in your case. arr will be empty after the call.
See example:
let arr = [1];
arr.splice(0, 1);
console.log(arr);
Array.prototype.splice() returns an array of the deleted elements.
Your are logging the returned value of the operation not the current state of the array.
The splice() method changes the contents of an array by removing
existing elements and/or adding new elements.
Reference
The syntax of this method is:
array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)
You are using the second syntax and passing 0 as start and 1 as deleteCount that means you would like to start at 0th index and delete 1 item (not 1 as value in array).
This method returns an array containing the deleted elements. If only one element is removed, an array of one element is returned. If no elements are removed, an empty array is returned.
So, in this case the result is [1] i.e. an array with value of 1 that is the item you just deleted.
I ran into this question when I was trying to achieve a function in mini-program. A solution is to check the array's length before using the function splice. For example:
if(imgList.length > 1){
imgList.splice(index, 1);
else{
imgList = []
}
You can try to solve it like that.

comparing 2 arrays with _.difference

Im using lodash with some calculations, but there is a function that isnt working has i expected, im using for example 'difference'.
His usage is:
_.difference([2, 1], [2, 3]);
output: [1]
But when i apply to my arrays:
_.difference([5111471, 5111513], [5111471,5111505,5111513]);
output:[]
Instead of giving me [5111505], is giving me a empty array.
_.difference returns elements of the first array not present in the second one. There are no such elements in your example, hence the empty result. If you want a symmetric difference (that is, elements that are present in the first array or the second, but not in both), you can do something like
diff = _.union(_.difference(a, b), _.difference(b, a))
_.difference doesn't actually return the difference between two arrays, but instead returns the first array minus the second. So to return [5111505] you need to do:
_.difference([5111471,5111505,5111513],[5111471, 5111513]);
See documentation for more info:
https://lodash.com/docs/4.15.0#difference

Categories