I'm using an Array as a container for some basic boilerplate objects which can be copied and added to another Array and then modified. The problem is when I assign the new array ownership of the object any changes persist down to the original object (which shouldn't change).
An example:
var originals = [{ name: "One", value: 1 }, { name: "Two", value: 2 }, { name: "Three", value: 3 }];
var notOriginal = [];
notOriginal.push(originals[0]);
// THIS GIVES ME - notOriginal = [{ name: "One", value: 1 }];
notOriginal[0].name = "Uno";
// THIS RESULTS IN - originals = [{ name: "Uno", value: 1 },...];
I'm trying to keep the "originals" variable the same - it shouldn't change.
I've googled quite a bit and tried some things but not sure where to find a solution.
Specifically this is happening in VueJS whereas the object is in my data()
Make a deep copy of it using JSON.parse & JSON.stringify
var originals = [{
name: "One",
value: 1
}, {
name: "Two",
value: 2
}, {
name: "Three",
value: 3
}];
var notOriginal = [];
notOriginal.push(JSON.parse(JSON.stringify(originals[0])));
notOriginal[0].name = "Uno";
console.log(originals)
You can use Object.assign to make a copy of the object.
var originals = [{
name: "One",
value: 1
}, {
name: "Two",
value: 2
}, {
name: "Three",
value: 3
}];
var notOriginal = [];
notOriginal.push(Object.assign({}, originals[0]));
notOriginal[0].name = "Uno";
console.log(originals);
Objects are passed by reference.
In order to copy an object you can use Object.assign({}, obj) which will return a new object with the duplicated properties within obj.
var originals = [{ name: "One", value: 1 }, { name: "Two", value: 2 }, { name: "Three", value: 3 }];
var notOriginal = originals.map(obj => Object.assign({}, obj));
notOriginal[0].name = "bart";
console.log(originals[0], notOriginal[0]);
I found a solution by using jQuery.extend(true, {}, myObj); but would still like to know what this is called so I can understand this reactivity better.
Thanks
Related
I'm receiving from backend side object which is formulated like:
[
{value: 'FIRST', AvailableValues[{code: "one"},{code: "two"}]},
{value: 'SECOND', AvailableValues[{code: "one"},{code: "two"}]
]
My question is how to map through this object to create pairs like
[{value: "FIRST", code:"one"},
{value: "FIRST", code:"two"},
{value: "SECOND", code:"one"},
{value: "SECOND", code:"two"}]
Thanks
I tried combination of javascript predefined methods like double map, keyed search and so on, but it resulted with errors
use reduce function
Also, your initial data should be an array because if it's a object, then it should contains key with values
const list = [
{value: 'FIRST', AvailableValues:[{code: "one"},{code: "two"}]},
{value: 'SECOND', AvailableValues:[{code: "one"},{code: "two"}]}
]
const result = list.reduce((acc,item) => {
const res = item.AvailableValues.map(i => ({value: item.value, code: i.code}))
return [...acc,...res]
}, [])
console.log(result)
Try something like this, Assuming that you receiving array of object from backend
let result = [];
yourObject.forEach((x)=>{
x.AvailableValues.map((innerItem)=>{
result.push({value:x.value, code : innerItem.code})
});
})
console.log(result)
The other answers here gets the job done. For completion here is an approach using flatMap combined with an inner map
const data =[
{value: 'FIRST', AvailableValues:[{code: "one"},{code: "two"}]},
{value: 'SECOND', AvailableValues:[{code: "one"},{code: "two"}]}
]
const res = data.flatMap(({value,AvailableValues}) => AvailableValues.map(({code}) => ({value,code})))
console.log(res)
var response = [{
value: 'FIRST', AvailableValues: [{ code: "one" }, { code: "two" }]},{
value: 'SECOND', AvailableValues: [{ code: "one" }, { code: "two" }]}
];
var output = [];
response.forEach(function(o) {
o.AvailableValues.forEach(function(oo) {
var t = {
value: o.value,
code: oo.code
};
output.push(t);
})
});
console.log(output);
I have one object and one is an array of objects like :
let obj = {
id:'1',
v1: '4',
v2: '2',
v3: '3',
}
const arr= [{key:1, value: 'v1'},{key:2, value:'v2'}]
here in the array of objects, I want concat values like this using key and value of obj
arr= [{key:1, value: 'v1:4'},{key:2, value:'v2:2'}]
basically, I just want to update the text value like this using object and an array of object
Note - every time I'm getting a new object so how can I achieve this in loop
You can use map().
let obj = {
id: "1",
v1: "4",
v2: "2",
v3: "3",
};
const arr = [
{ key: 1, value: "v1" },
{ key: 2, value: "v2" },
];
const result = arr.map(({ key, value }) => ({ key, value: `${value}:${obj[value]}` }));
console.log(result)
This solution uses object destructuring to get the key and value and looks up the values in the object using obj[value].
Try this :
let obj = {
id: '1',
v1: '4',
v2: '2',
v3: '3',
};
const arr= [{key:1, value: 'v1'},{key:2, value:'v2'}];
arr.forEach((arrayObj, index) => {
arr[index].value = Object.keys(obj).includes(arrayObj.value) ? `${arrayObj.value}:${obj[arrayObj.value]}` : arrayObj.value
});
console.log(arr);
How can I merge two arrays of objects of same length?
var array1 = [
{name: "lang", value: "English"},
{name: "age", value: "18"}
];
var array2 = [
{code: "EN", text: "English language"},
{code: "DE", value: "German", text: "German language"}
];
The goal is to create the following array:
var array3 = [
{name: "lang", value: "English", code: "EN", text: "English language"},
{name: "age", code: "DE", value: "German", text: "German language"}
];
The idea is to create a new array in which array1 is the base and array2 overrides the values if they share the same key, and otherwise adds to the base array. The merging should happen sequentially in the same order that the objects appear in each array.
In this example, the arrays contains two objects, but for my actual situation, I have a couple of dozens of objects.
This is what I’ve been trying to do, but this only merges the first set of objects:
var array3 = Object.assign(array1[0], array2[0]);
How can I loop through it or map it?
A simple map with object spread syntax will do it.
Instead of object spread, Object.assign can also be used.
Assign unto a new empty object in order to avoid mutating the existing objects.
var array1 = [
{ name: "lang", value: "English" },
{ name: "age", value: "18" }
];
var array2 = [
{ code: "EN", text: "English language" },
{ code: "DE", value: "German", text: "German language" }
];
var array3 = array1.map((obj, index) => ({
...obj,
...array2[index]
}));
var array3Alternative = array1.map((obj, index) => Object.assign({}, obj, array2[index]));
console.log(array3);
Note that the order of spread patterns and Object.assign’s arguments matters: latter properties overwrite former properties.
You can also add more properties, e.g. default properties: Object.assign({ code: "XX", value: "Default" }, obj, array2[index]) or ({ code: "XX", value: "Default", ...obj, ...array2[index] }).
If you want to mutate the objects in array1, so that the properties from array2 get added into array1, simply remove the {}, from Object.assign({}, obj, array2[index]).
Then it would also be advisable to change the map to a forEach if you’re not expecting to create a resulting variable like array3.
If you have an unknown number of arrays like this:
const arrays = [
array1,
array2,
array3,
// …
];
then you can use this approach:
const mergedArray = Array.from({
length: arrays[0].length
}, (_, index) => Object.assign({}, ...arrays.map(({[index]: obj}) => obj))));
See this in action with the following example:
const arrays = [
[
{ a: 3, b: 5 },
{ a: 7, b: 2 },
{ a: 1 }
],
[
{ b: 8, c: 42 },
{ a: 1, b: 12, c: 44 },
{ b: 0 }
],
[
{ d: 14, e: 15 },
{ d: 7 },
{ a: 10 }
]
];
console.log(Array.from({
length: arrays[0].length
}, (_, index) => Object.assign({}, ...arrays.map(({[index]: obj}) => obj))));
Note that this also works with arrays of different lengths.
The resulting value from accessing a non-existent array index is undefined and spread syntax and Object.assign take care of this by ignoring it.
Just make sure to start with the longest array, so the result isn’t missing any objects.
This is easier with the snippet where you have an unknown number of arrays (even if it’s always two).
Instead of arrays[0].length, you just need to use Math.max(...arrays.map(({ length }) => length)).
I have the following array, which has an object holding nested arrays that in turn have objects of their own:
var list = [{
one: [{key: 1, value: 'eng1'}, {key: 2, value: 'eng2'}],
two: [{key: 1, value: 'esp1'}, {key: 2, value: 'esp2'}]
}];
I want to group the data above by the key property inside the objects of the nested arrays. The following is the desired structure:
var grouped = [
{
key: 1,
group: {
one: {
value: 'eng1'
},
two: {
value: 'esp1'
}
}
},
{
key: 2,
group: {
one: {
value: 'eng2'
},
two: {
value: 'esp2'
}
}
}
]
I have tried so many ways to achieve the above structure but to no avail. I have tried using reduce but that was mainly applicable if the objects were not deeply nested. My problem is the fact that the arrays are nested inside the objects and the key is embedded in those objects. Your help would be greatly appreciated.
The requirement is to not use any library such as underscore or lodash. I have to get this working with plain JS.
You can use multiple forEach loops because of your data structure and add to new array.
var list = [{
one: [{key: 1, value: 'eng1'}, {key: 2, value: 'eng2'}],
two: [{key: 1, value: 'esp1'}, {key: 2, value: 'esp2'}]
}];
var grouped = [];
list.forEach(function(e) {
Object.keys(e).forEach(function(k) {
var that = this;
e[k].forEach(function(a) {
if(!that[a.key]) grouped.push(that[a.key] = {key: a.key, group: {}})
Object.assign(that[a.key].group, {[k]: {value: a.value}})
})
}, {})
})
console.log(grouped)
You may try for this:
var list = [{
one: [{key: 1, value: 'eng1'}, {key: 2, value: 'eng2'}],
two: [{key: 1, value: 'esp1'}, {key: 2, value: 'esp2'}]
}];
var grouped = [];
list.forEach(function(e) {
Object.keys(e).forEach(function(k) {
var that = this;
e[k].forEach(function(a) {
if(!that[a.key]) grouped.push(that[a.key] = {key: a.key, group: {}})
Object.assign(that[a.key].group, {[k]: {value: a.value}})
})
}, {})
})
console.log(grouped)
In lodash, how can I get an object from an array by the index at which it occurs, instead of searching for a key value.
var tv = [{id:1},{id:2}]
var data = //Desired result needs to be {id:2}
Let's take for example this collection:
var collection = [{id: 1, name: "Lorem"}, {id: 2, name: "Ipsum"}];
I will talk about two approaches, indexing and not indexing.
In general, indexing is better if you want to access many of the items, because you loop the collection once. If not, Meeseeks solution with find is the right choice.
Indexing
var byId = _.groupBy(collection, 'id');
var byName = _.groupBy(collection, 'name');
now you can reach each item by it indexed key:
console.log(byId[2]); // Object {id: 2, name: "Ipsum"}
console.log(byName.Lorem); // Object {id: 1, name: "Lorem"}
Without indexing
var item = _.find(collection, {id: 2});
console.log(item); // Object {id: 2, name: "Ipsum"}
I think what you're looking for is find
You can give it an object and it will return the matched element or undefined
Example
var arr = [ { id: 1, name: "Hello" }, { id: 2, name: "World" } ];
var data = _.find(arr, { id: 1 }); // => Object {id: 1, name: "Hello"}
var data = _.find(arr, { id: 3 }); // => undefined