Remove and update an array without mutation in Javascript - javascript

I have an array :
let originalArr = ['apple', 'plum', 'berry'];
How can I remove "plum" from this array without mutating the originalArr?
I can think of below approach :
let copyArr = [...originalArr];
originalArr = copyArr.filter(item => {
return item !== 'plum';
});

You're creating two additional arrays: one copyArr and one filtered array. There's no need for both, creating just the filtered array should work fine, eg:
setOriginalArr(
originalArr.filter(item => item !== 'plum')
);
as an example, if originalArr is in state.
Calling .filter on an array doesn't mutate the array it was called on - it returns a new, separate array, so it's safe to use in React without cloning the original array beforehand.

You can use slice() method to extract items from/to specific indexes (without mutation of original array)
let originalArr = ['apple', 'plum', 'berry'];
let sliced = originalArr.slice(1, 2)
console.log(originalArr, sliced)

Related

updating value of object inside of array based on id of different object in different array in react

if I have an array like this:
const[arr,setArr] = React.useState([
{label:"dummy01",id:2},
{label:"dummy02",id:5},
])
is there anyway to update arr with such array:
const newArray = [{label:'dummy Altered01',id:2},{label:'different',id:10},{label:'different 02',id:55}}
what I expect to have an array like this :
[
{label:"dummy Altered01",id:2},
{label:"dummy02",id:5},
{label:'different',id:10},
{label:'different 02',id:55}
]
as you can see the object with the id of 2 is updated and other new objects are added to the array without erasing previous dummy02.
I don't know how should I compare id inside of two different arrays
I know this is not the best answer, so here's what I got
let listOfIds = newArray.map(item => item.id)
newArray = newArray.concat(arr.filter(item => !listOfIds.includes(item.id)))
First you map the newArray into a list of IDs.
Then newArray concatenates with the filtered original array (i.e. the array now doesn't have any items with ids in common with the latter )
Finally you update the state by setArr(newArr)
Hope this answers your question
Lets consider
a = [{label:"dummy01",id:2},{label:"dummy02",id:5}]
and new array is
b= [{label:'dummy Altered01',id:2},{label:'different',id:10},{label:'different 02',id:55}]
Now perform itearation over new array
b.forEach((item)=>{
let index = a.findIndex((x)=>x.id == item.id)
if(index > -1){
a[index].label = item.label
}
else
a.push(item)
})
console.log(a)

Check if an array of arrays contains a value in javascript

I know that if there is an array of values it must be used this approach:
console.log(['joe', 'jane', 'mary'].includes('jane')); // true
But in case of an array of arrays, is there a short way to do it? Without other computations between.
For this input:
[['jane'],['joe'],['mary']]
You can use flat method to flatten the array. For more neted array, you can also mention depth like flat(depth)
let arr = [["jane"],["joe"],["mary"]];
arr.flat().includes('jane'); //true
You can easily achieve this result using some
arr.some((a) => a.includes("jane"))
const arr = [
["jane"],
["joe"],
["mary"]
];
const arr2 = [
["joe"],
["mary"]
];
console.log(arr.some((a) => a.includes("jane")));
console.log(arr2.some((a) => a.includes("jane")));
it can also be done by first flattening the 2d arrays in 1 d aaray and then using includes to find whether the array contains the element or not
var arr = [['jane'],['joe'],['marry']]
var newarr=[].concat(...arr)
var v=newarr.includes('jane')
console.log(v)

Reducing a 2D array taking into account another 2D array

I have two 2D arrays with identical elements but in a different order. I want to filter one taking into account if it already exists in the second array.
Examples of both arrays:
const firstArray = [['45614726','2020-4-28'],['45610125','2020-4-28'],['45880944','2020-4-28'],['43452341','2020-4-28']] // there are like 40 arrays inside, not sorted
const secondArray = [['34347896', '2020´4-30'],['45614726','2020-4-28'],['45610125','2020-4-28'],['45880944','2020-4-28'],['45892916','2020-4-28']] // there are like 300 arrays inside, not sorted
I want to eliminate the arrays of the "secondArray" that have the first index repeated in the "firstArray".
secondArray =[['34347896', '2020´4-30'], ['45892916','2020-4-28']]
I tried several things, I know that the most useful action is to use .reduce but it seems that I cannot make it work.
const notPosted = secondArray.reduce((a, b) => {
if (!firstArray[a[0]]) a.different.push(b);
return a;
}, {different: []});
Thanks!
I dont know which one is faster:
const arr1 = [['45614726','2020-4-28'],['45610125','2020-4-28'],['45880944','2020-4-28'],['43452341','2020-4-28']]
const arr2 = [['34347896', '2020´4-30'],['45614726','2020-4-28'],['45610125','2020-4-28'],['45880944','2020-4-28'],['45892916','2020-4-28']];
//First solution:
console.log("1) ",arr2.filter(e=>!arr1.some(e2=>JSON.stringify(e2)==JSON.stringify(e))))
//Second:
console.log("2) ",arr2.filter(e=>!arr1.some(e2=>e[0]==e2[0]&&e[1]==e2[1])))
You could convert your 2D array into an object with the zero index of each nested array being the key, and the first index being the value. (i.e. you already have your array in the perfect form for this [[key, val], [key, val], ...])
This is easy with Object.fromEntries(firstArray);
Then you call a simple filter function on your second array and return only those that have a key that is not in the object (lookups of keys in an object are fast - hash tables)
// there are like 40 arrays inside, not sorted
const firstArray = [['45614726','2020-4-28'],['45610125','2020-4-28'],['45880944','2020-4-28'],['43452341','2020-4-28']]
// there are like 300 arrays inside, not sorted
const secondArray = [['34347896', '2020´4-30'],['45614726','2020-4-28'],['45610125','2020-4-28'],['45880944','2020-4-28'],['45892916','2020-4-28']];
const firstObj = Object.fromEntries(firstArray);
const secondFiltered = secondArray.filter(([key,val]) => !firstObj.hasOwnProperty(key));
console.log(secondFiltered);

push method not returning new array

I am adding an object to an array through javascript push() method. My array is an array of objects. I want to console.log() the new array. But it is giving me the length of new array. I know push() method returns the length of new array but I want to use the new array in my application. How to get it
let sub_sprite = this.state.sub_sprite;
let updated_sub_subsprite;
updated_sub_subsprite = sub_sprite.push(this.state.sprite[that.state.sprite_count]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite:updated_sub_subsprite}, ()=>{
console.log(this.state.sub_sprite)
});
Do not use Array.push on an array stored in your React component's state, it will mutate the state directly, which may lead to problems (see this article).
You can use Array.concat to create a new array with the additional value:
let sub_sprite = this.state.sub_sprite
let updated_sub_subsprite;
updated_sub_subsprite = sub_sprite.concat([this.state.sprite[that.state.sprite_count]]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite:updated_sub_subsprite}, ()=> {
console.log(this.state.sub_sprite)
})
A more consise and convenient way is using the spread syntax (notice the three dots):
let sub_sprite = this.state.sub_sprite
let updated_sub_subsprite;
updated_sub_subsprite = [...sub_sprite, this.state.sprite[that.state.sprite_count]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite:updated_sub_subsprite}, ()=> {
console.log(this.state.sub_sprite)
})
The Array#push method does not return a new array, but rather the length of the array after the item(s) have been added to that array instance.
It looks like the Array#concat method would be a better fit for what you're trying to do, seeing that offers the "appending behavior" and also returns the resulting array.
Consider making the following adjustments to your code, making use of concat() to achieve what you want:
let sub_sprite = this.state.sub_sprite;
// Create a new array via concat(), adding a new array with one item
// that is [ sub_sprite [that.state.sprite_count] ] to sub_sprite
let updated_sub_subsprite = sub_sprite.concat( [ sub_sprite [that.state.sprite_count] ]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite : updated_sub_subsprite }, ()=>{
console.log(this.state.sub_sprite)
})

Create new array without impacting values from old array

I'm trying to create a copy of existing array and remove some items from array copy without impacting the original. I've tried this :
var new_arr = old_arr; //when I remove from new array the items from old array are also removed
How do I create entirely new copy of the existing array?
Update :
When I do this :
var new_arr = old_arr.slice();
then later :
new_arr[0].shift();
new_arr[1].shift();
The items from old_array get removed. This is a two dimensional array.
You can use two methods, this:
function clone (src) {
return JSON.parse(JSON.stringify(src));
}
or this:
var newArray = oldArray.slice();
A newer solution to do this is to use 'from' like this:
const newArr = Array.from(oldArr);
But this is a shallow copy and if nested elements are mutated they will project in the new created array with from. Best solution then would be to use
const newArr = JSON.parse(JSON.stringify(oldArr));
but also that method doesn't ensure all. If for example an element of the array contains a function like n => ++n then it will be null after using the JSON methods so best solution is deepClone and for that full explanation I refer to
Creating JavaScript Arrays
Using Yoshi answer you can extend Array prototype (just a simple helper):
Array.prototype.clone = function() {
return this.slice(0);
}
In Javascript, a two-dimensional array is just an array of arrays. Therefore, cloning one dimension is not enough. We also need to clone all the sub-dimension arrays. Here’s how we do it:
function cloneGrid(grid) {
// Clone the 1st dimension (column)
const newGrid = [...grid]
// Clone each row
newGrid.forEach((row, rowIndex) => newGrid[rowIndex] = [...row])
return newGrid
}
// grid is a two-dimensional array
const grid = [[0,1],[1,2]]
newGrid = cloneGrid(grid)
console.log('The original grid', grid)
console.log('Clone of the grid', newGrid)
console.log('They refer to the same object?', grid === newGrid)
---
The original grid [ [ 0, 1 ], [ 1, 2 ] ]
Clone of the grid [ [ 0, 1 ], [ 1, 2 ] ]
They refer to the same object? false
Or if we take avantage of ES6 Array.map operation, we can make cloneGrid function even simpler:
const cloneGrid = (grid) => [...grid].map(row => [...row])
For more expanded answer read How to make a copy of an array in JavaScript
You can try .concat()
var old_arr = [1,2,3,4,5]
var new_arr = old_arr.concat()
console.log(old_arr) //1,2,3,4,5
console.log(new_arr) //1,2,3,4,5
new_arr.shift()
console.log(old_arr) //1,2,3,4,5
console.log(new_arr) //2,3,4,5
you may create a new array by using the spread operator. You can also find more about spread operator HERE.
cosnt oldArr = [{id: 1, name: 'Ali'}, {id:2, name: 'Raza'}];
cosnt newArray = [...oldArr];
console.log(newArray);

Categories