Related
I have 2 arrays containing objects, I want to create a new array without "duplicates". The problem is that the two arrays are not identical and I want to choose based on id.
This is a simple version of what I got:
let array1 = [
{
"id": "1",
"type": "abc"
},
{
"id": "2",
"type": "one, two, three"
}
]
let array2 = [
{
"id": "1",
"type": "abc",
"country": "England"
},
{
"id": "3",
"type": "one, two, three",
"country": "Germany"
}
]
let array3 = array1.filter(x => array2.forEach(y => x.id === y.id)).concat(array2);
The result I want for array3 is:
{
"id": "1",
"type": "abc"
}
In this particular case country is not important and will be thrown away anyway.
How do I filter out unwanted objects and create a new array with only the objects I want?
If you are looking for an intersection between the arrays the shortest answer is to use the filter with a find.
let array1 = [{
id: '1',
type: 'abc',
},
{
id: '2',
type: 'one, two, three',
},
];
let array2 = [{
id: '1',
type: 'abc',
country: 'England',
},
{
id: '3',
type: 'one, two, three',
country: 'Germany',
},
];
const array3 = array1.filter(value => array2.find((a)=>a.id==value.id));
console.log(array3);
let array1 = [{
id: '1',
type: 'abc',
},
{
id: '2',
type: 'one, two, three',
},
];
let array2 = [{
id: '1',
type: 'abc',
country: 'England',
},
{
id: '3',
type: 'one, two, three',
country: 'Germany',
},
];
array2.forEach((el, idx) => {
const match = array1.find((el2) => el2.id === el.id);
if (!match) array1.push(el);
});
console.log(array1);
Something like this ? I assumed from your explanation that you want to merge array2 with array1.
You will end up with the unique objects from array2 having the extra country property, if you want to delete that you need an extra step before pushing.
I think this is what you were trying to achieve:
let array1 = [ { "id": "1", "type": "abc" }, { "id": "2", "type": "one, two, three" } ];
let array2 = [ { "id": "1", "type": "abc", "country": "England" }, { "id": "3", "type": "one, two, three", "country": "Germany" } ];
let array3 = array1.filter(x => array2.map(y => y.id).includes(x.id));
console.log( array3 );
In order to avoid have to recompute the array2 array of ids you can get them in advance as follows:
let array1 = [ { "id": "1", "type": "abc" }, { "id": "2", "type": "one, two, three" } ];
let array2 = [ { "id": "1", "type": "abc", "country": "England" }, { "id": "3", "type": "one, two, three", "country": "Germany" } ];
const ids = array2.map(({id}) => id);
let array3 = array1.filter(x => ids.includes(x.id));
console.log( array3 );
I have an object
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
Need to filter this from below array, with array index as object.key
const myFilter = [123,789];
Code I am trying is as below but it returning array inedx as 0,1,2... but I need the index to be object.key.
let selectedItems = myFilter.map((key) => {
return items[key];
});
Current output :
[0:{
key: 123,
name: "one name"
}, 1: {
key: 789,
name: "three name"
}]
Expected Output
[123:{
key: 123,
name: "one name"
}, 789: {
key: 789,
name: "three name"
}]
jsfiddle - https://jsfiddle.net/kb374exh/2/
Your actual output is actually correct and the only possible result from mapping the myFilter array to the matching properties from items.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = myFilter.map((key) => items[key]);
console.log(selectedItems);
The logged output you see is including the array index. You likely are seeing the index included when logging in the browser.
If you want an array of objects where the original key is the new index then the best you can likely do is an array of length <highest key> and a bunch of "holes" that are simply undefined.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = Object.entries(items).reduce((selectedItems, [key, value]) => {
if (myFilter.includes(value.key)) selectedItems[key] = value;
return selectedItems;
}, []);
console.log(selectedItems);
If you are ok with the result being an object then you can have more succinct output, you'll basically end up with back with an object with key-value pairs filtered out.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = Object.fromEntries(Object.entries(items).filter(([, value]) => myFilter.includes(value.key)));
console.log(selectedItems);
I have two arrays of objects:
1)
[
{
"userId": 9
},
{
"userId": 14
}
]
2)
[{"role": "1", "group": "3"}, {"role": "1", "group": "2"}]
I would like to merge two arrays as follows:
[
{"userId":9,"role":"1","group":"2"},
{"userId":14,"role":"1","group":"2"}
{"userId":9,"role":"1","group":"3"},
{"userId":14,"role":"1","group":"3"}
]
I tried to use let however I couldn't find the way to manipulate switch the subarray :
let arr1 = [{"userId": 9}, {"userId": 14}];
let arr2 = [{"role": "1", "group": "3"}, {"role": "1", "group": "2"}];
let result = arr1.map(o => Object.assign(o, ...arr2));
console.log(result);
return result;
The result I got with the previous implementation is like this :
[{"userId":9,"role":"1","group":"2"},{"userId":14,"role":"1","group":"2"}]
However, I would like to get the result as follows :
[
{"userId":9,"role":"1","group":"2"},
{"userId":14,"role":"1","group":"2"}
{"userId":9,"role":"1","group":"3"},
{"userId":14,"role":"1","group":"3"}
]
var a = [{
"userId": 9
},
{
"userId": 14
}
]
var b = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}]
console.log(
b.map(z=>a.map(x=>({...x, ...z}))).flat()
)
Another solution using for loop
let arr1 = [{ "userId": 9 }, { "userId": 14 }]
let arr2 = [{"role": "1","group": "3"}, {"role": "1","group": "2" }]
let result = [];
for (let group of arr2) {
for (let user of arr1) [
result.push(Object.assign({}, group, user))
]
}
console.log(JSON.stringify(result))
//output is:
// [
// {"role":"1","group":"3","userId":9},
// {"role":"1","group":"3","userId":14},
// {"role":"1","group":"2","userId":9},
// {"role":"1","group":"2","userId":14}
// ]
Stackblitz example
To achieve expected result, use below option of looping through two arrays
var x = [
{
"userId": 9
},
{
"userId": 14
}
]
var y = [{"role": "1", "group": "3"}, {"role": "1", "group": "2"}]
let result = []
y.forEach((v, i) =>{
x.forEach((y,i) => result.push({...v, ...y}))
})
console.log(result);
codepen - https://codepen.io/nagasai/pen/pxvzOG?editors=1010
You could iterate over the two arrays like this and push the merged values into result:
arr1.forEach(e => {
arr2.forEach(e2 => {
result.push(Object.assign({}, e, e2));
});
});
Which could also be written in ONE LINE:
arr1.forEach(e => arr2.forEach(e2 => result.push(Object.assign({}, e, e2))));
const arr1 = [{
"userId": 9
},
{
"userId": 14
}
];
const arr2 = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}];
const result = [];
arr1.forEach(e => {
arr2.forEach(e2 => {
result.push(Object.assign({}, e, e2));
});
});
console.log(result);
You can use a mix a reduce and map to boil it down to a single array of objects.
let data = [{
"userId": 9
},
{
"userId": 14
}
]
let metaData = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}];
let dataReducer = data.reduce((acc, curr) => {
let metadataReducer = metaData.map((val) => {
return {
...curr,
...val
};
}, []);
return [...acc, ...metadataReducer];
}, []);
console.log(dataReducer)
Here a short approach for an arbitrary count of arrays of objects.
var array1 = [{ userId: 9 }, { userId: 14 }],
array2 = [{ role: "1", group: "3" }, { role: "1", group: "2" }],
result = [array1, array2]
.reduce((a, b) =>
a.reduce((r, v) =>
r.concat(b.map(w => Object.assign({}, v, w))), []));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You're basically asking for a Cartesian product of the two arrays. flatMap is a useful function here. For each element of one array, merge it with all objects from the other array, then return a flat result.
const a = [{userId: 9}, {userId: 14}];
const b = [{role: "1", group: "3"}, {role: "1", group: "2"}];
const merged = b.flatMap(ae => a.map(be => ({...be, ...ae})));
console.log(merged);
So i have an array which stores hobbies for each user in an array within the object..
var hobbies = [
{
"id": 1,
"hobbies": []
},
{
"id": 2,
"hobbies": [
"football"
]
},
{
"id": 3,
"hobbies": [
"football",
"basketball"
]
}
]
What i want to return is a new array of objects but each hobby separated into their own object like below.
var result = [
{
"id": 2,
"hobby": "football"
},
{
"id": 3,
"hobby": "football"
},
{
"id": 3,
"hobby": "basketball"
}
]
What is have so far is
hobbies.filter((f, i) => f.hobbies.length > 0).map((p, i) => {
while (i < p.hobbies.length) {
return { id : p.id, hobby : p.hobbies[i] };
}
});
which only returns
[
{
"id": 2,
"hobby": "football"
},
{
"id": 3,
"hobby": "basketball"
}
]
You can use array#reduce with array#map. Iterate through each object and then iterate through each hobby of hobbies and create the object.
var hobbies = [ { "id": 1, "hobbies": [] }, { "id": 2, "hobbies": [ "football" ] }, { "id": 3, "hobbies": [ "football", "basketball" ] } ],
result = hobbies.reduce((r, {id, hobbies}) => r.concat(hobbies.map(hobby => ({id, hobby}))), []);
console.log(result);
I know, "functional" programming is considered "cool" around these parts, however, have you considered using simple loops to, well, loop over your data?
let result = [];
for (let {hobbies, id} of data)
for (let hobby of hobbies)
result.push({id, hobby})
In my opinion, this is far more readable than any reduce spaghetti one could come up with ;)
You need to use inner-loop to loop through the hobbies and push them one-by-one to the target array:
var hobbies = [{
"id": 1,
"hobbies": []
},
{
"id": 2,
"hobbies": [
"football"
]
},
{
"id": 3,
"hobbies": [
"football",
"basketball"
]
}
];
var result = hobbies.reduce((acc, item) => {
item.hobbies.forEach(hobby => {
acc.push({
id: item.id,
hobby: hobby
});
});
return acc;
}, []);
console.log(result);
You can use array.prototype.reduce:
var hobbies = [{"id": 1,"hobbies": []},{"id": 2,"hobbies": ["football"]},{"id": 3, "hobbies": ["football","basketball"]}];
var res = hobbies.reduce((m, o) => (o.hobbies.forEach(h => m.push({id: o.id, hobby: h})), m), []);
console.log(res);
You need nested loops and this is the basics of it:
You first need to loop over the main hobbies array.
Then for each item in the array (which represents a person), you want to loop through their hobbies, and for each one of those hobbies, you need to push an object made up of the profile ID and the hobby into results array I created earlier.
var hobbies = [{ "id": 1, "hobbies": [] }, { "id": 2, "hobbies": [ "football" ] }, { "id": 3, "hobbies": [ "football", "basketball" ] } ];
let result = [];
hobbies.forEach(function(profile){
profile.hobbies.forEach(function(hobby){
result.push(
{
"id": profile.id,
"hobby": hobby
}
);
});
});
console.log(result)
Update: the other answers with Array.reduce (a more specialised loop) will cut the above code down even further.
This question already has answers here:
javascript: convert two dimensional array to array of objects using the first 'row' to define properties
(8 answers)
Closed 2 years ago.
I have a variable that is returning an array of arrays, with each item in each array in double quotes.
var arrayOfArrays = [
[ "Name", "Age", "Address" ],
[ "A", "43", "CA" ],
[ "B", "23", "VA" ],
[ "C", "24", "NY" ]
]
I need to convert this to the following:
var arrayOfObjects = [
{"Name":"A", "Age":"43", "Address":"CA"},
{"Name":"B", "Age":"23", "Address":"VA"},
{"Name":"C", "Age":"24", "Address":"NY"}
]
Update
Less verbose version using Array.prototype.reduce() with newer language constructs like destructuring and computed property names:
const arrays = [
["Name", "Age", "Address"],
["A", "43", "CA"],
["B", "23", "VA"],
["C", "24", "NY"]
];
const [keys, ...values] = arrays;
const objects = values.map(array => array.reduce((a, v, i) => ({...a, [keys[i]]: v}), {}));
console.log(JSON.stringify(objects));
Original answer
Using Array.prototype.slice(), Array.prototype.map() and Array.prototype.forEach():
const arrays = [
["Name", "Age", "Address"],
["A", "43", "CA"],
["B", "23", "VA"],
["C", "24", "NY"]
];
const keys = arrays[0];
const values = arrays.slice(1);
const objects = values.map(array => {
const object = {};
keys.forEach((key, i) => object[key] = array[i]);
return object;
});
console.log(JSON.stringify(objects));
Hope this helps
var arrayOfArrays = [
[ "Name", "Age", "Address" ],
[ "A", "43", "CA" ],
[ "B", "23", "VA" ],
[ "C", "24", "NY" ]
]
var arrayOfObjects = [];
function changeToObject(arrayOfArrays){
for (var i = 1; i < arrayOfArrays.length; i++) {
var json = {
"Name" : "",
"Age" : "",
"Address" : ""
}
json.Name = arrayOfArrays[i][0];
json.Age = arrayOfArrays[i][1];
json.Address = arrayOfArrays[i][2];
arrayOfObjects.push(json);
};
console.log(arrayOfObjects)
}
changeToObject(arrayOfArrays);