Create new array without impacting values from old array - javascript

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

Related

Array of objects, remove the array after push, keep objects

Im trying to push my array of objects into variable, but all i I recieve is Array in Array, or single object.
myObject = {
id: id,
items: [],
boolean: true,
}
myArray = [{1}, {2}, {3}]
I tried myObject.items.push(myArray[0]) but this returns only first object. Without 0 its double array.
What i want is
myObject = {
id: id,
items: [{1}, {2}, {3}],
boolean: true,
}
What you're going to want to do here is set the entire array as the new value like this:
myObject.items = myArray
If you want to take the immutable approach then you can copy it like this:
myObject.items = [...myArray]
Edit:
If you want to add items (and not just complete overwrite) to myObject.items then you should do this:
myObject.items = [...myObject.items, ...myArray]
That will add your new array items to the end of the current items array, you could also do this to add them to the start:
myObject.items = [...myArray, ...myObject.items]
you can use this
myObject.items.push(...myArray)
As Andreas commented another solution is to use concat. Concat is similar to push. But it doesn't actually change the array it returns a new one.
const x = []
console.log(x.concat(3)) // prints [3]
console.log(x) // prints []
This behavior is often desired as it prevents "side effects" from occurring
It also doesn't just append items to an array, it only does this if the item is not an array. If it is an array it will merge the two arrays
const x = [1,2,3]
console.log(x.concat([4,5,6]) // prints [1,2,3,4,5,6]
so a solution here is
myObject.items = myObject.items.concat(myArray)
//object
myObject={
id:1,
items:[],
boolean: true
}
//concat
myArray = [ 1,2,3];
myObject.items += myArray;
console.log(myObject.items);

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)

Remove and update an array without mutation in 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)

can I use forEach to make every element of an array a new object?

I created an array with many elements with a loop:
myArray = [c1, c2, c3...]
now I want to make each element into an object and assign different key values:
c1 = {image = path, value = number)
I tried to run forEach() but can't figure out the correct way to do so and I have not succeeded in finding the answer to it.
My guess was:
myArray.forEach(function() {
let name = {
image = path,
value = number,
}
return name;
});
but there's no change in the elements in the log.
Any help or link to an answer that can help me here. First time coding here.
UPDATE: an easier solution was to .push all the keys and values of the objects when I created the array with the loop in the first place.
array.push({image: pathx, value: numberx})
You can, but you'd be better off with a simple for loop:
for (let i = 0; i < myArray.length; ++i) {
let entry = myArray[i];
myArray[i] = {image: entry.path, value: entry.number};
}
Or making a new array with map.
newArray = myArray.map(entry => ({image: entry.path, value: entry.number}));
Or if you prefer non-arrow functions:
newArray = myArray.map(function(entry) {
return {image: entry.path, value: entry.number};
});
You could theoretically push to a new array but this is the exact usecase for Array#map. Array#map maps old values to new values. The returned object from the callback is the new object and the returned array is the new array containing the new objects.
Semantically, Array#forEach is to plainly iterate over each element in an array, and possibly execute something with side-effects (which may include pushing to another array). But with Array#map, it's specifically used to transform old array values to new ones. Use the one that is specifically designed because it conveys a clear message to anyone else who reads your code.
const newArray = myArray.map(({ path, number }) => ({
image: path,
value: number
}));
Array#map maps old values to new values. You may need to use the follwing instead of arrow functions as it is not supported in IE.
I just added dummy data in the object, you can change it.
myArray = ["c1", "c2", "c3"]
myArray = myArray.map(function(elem) {
return {"image":"path"+elem,"value":"value"+elem};
});
console.log(myArray);

Javascript: Sorting Objects Challenge

I have a bit of a challenge. I am working on a physics application with javascript. The two main objects being used are
var force = new Object();
var torque = new Object();
with properties
force.magnitude = newArray();
force.lengthfromorigin = new Array();
force.count;
torque.lengthfromorigin= new Array();
torque.count;
now, I'd like to sort these two objects into an array based on their respective lengthfromorigins
Example: force.lengthfromorigin = [5,8] and torque.lengthfromorigin=[2,6]
so their order in this newArray would be [ torque[0], force[0], torque[1], force[1] ]
My question is it possible to have an array of different objects sorted by their respective properties, and to then use this array in a function which will make decisions based on which object is at the index. Also will I need to have an id property in each respective object to identify if the object is a torque or force.
Example:
if(newArray[i] == torque)
//do stuff
else
//do other stuff.
Something like this perhaps?
Let me explain the algorithm:
Create a new array let it be called A.
For each objects in objects:
2.1 Let the current object be called obj.
2.2 Use map to generate a new array called tuples of [obj, num] tuples
for each lengthFromOrigin numbers of obj.
3.3 Push all items of tuples into A.
Sort A on tuple[1] (which is the number) ascending.
var objects = [
{ type: 'force', lengthFromOrigin: [5, 8] },
{ type: 'torque', lengthFromOrigin: [2, 6] }
],
sorted = objects.reduce(function (arr, obj) {
arr.push.apply(arr, obj.lengthFromOrigin.map(function (num) {
return [obj, num];
}));
return arr;
}, []).sort(function (a, b) {
return a[1] - b[1];
});
console.log(sorted);
Then you can loop over sorted and easily identify if it's a torque or force by looking at the first element in the tuple.
sorted.forEach(function (tuple) {
console.log(tuple[0].type, tuple[1]);
});
//torque 2
//force 5
//torque 6
//force 8
The answer is Yes,
But you have to identify each object before you access their properties. In your case Both of the objects have a common property called lengthfromorigin which can be used to sort them properly.
To identify each object you can use a property like ID or Name.
if(Mydata[i].Name = 'torque'){
//your code goes here
}
else if(Mydata[i].Name = 'force'){
//your code goes here
}
Hope this will help you

Categories