I want to filter the items array objects which match the "model" key in the models array and store them in an array. I did succeed in my attempt but I am not very satisfied with my effort. Are there any better ways of doing it?
Any suggestions on how to do it using underscore.js and lodash? Or using the native javascript map and filter functions?
The JSON object
{
"items": [
{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
],
"models": [
{
"model": "ruie9",
"year": 1998
},
{
"model": "ooc0d",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
},
{
"model": "ddebd",
"year": 1995
},
{
"model": "odq76",
"year": 1999
}
]
}
My Solution
const { models, items } = jsonData;
const newarray = [];
for(let i = 0; i < models.length; i++) {
for(let j = 0; j < items.length; j++) {
if(items[j].model===models[i].model) {
let obj = {
...items[j],
year: models[i].year
}
newarray.push(obj);
}
}
}
I want to filter the items array objects which match the "model" key in the models array and store them in an array. I did succeed in my attempt but I am not very satisfied with my effort. Are there any better ways of doing it?
Any suggestions on how to do it using underscore.js and lodash? Or using the native javascript map and filter functions?
The JSON object
{
"items": [
{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
],
"models": [
{
"model": "ruie9",
"year": 1998
},
{
"model": "ooc0d",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
},
{
"model": "ddebd",
"year": 1995
},
{
"model": "odq76",
"year": 1999
}
]
}
My Solution
const { models, items } = jsonData;
const newarray = [];
for(let i = 0; i < models.length; i++) {
for(let j = 0; j < items.length; j++) {
if(items[j].model===models[i].model) {
let obj = {
...items[j],
year: models[i].year
}
newarray.push(obj);
}
}
}
Share
Improve this question
edited May 31, 2017 at 22:26
1033
asked May 31, 2017 at 22:11
10331033
611 silver badge9 bronze badges
3
-
1
in your code you access the
id
property but there is not track of id property in your JSON – quirimmo Commented May 31, 2017 at 22:23 - Oops I am sorry. Just corrected – 1033 Commented May 31, 2017 at 22:28
- @created this benchmark with me Umair and Pankaj. Pankaj wins :) – Karen Grigoryan Commented May 31, 2017 at 23:06
4 Answers
Reset to default 3I would take a slightly different approach. I guess you might like it.
const models = [
{
"model": "ruie9",
"year": 1998
},
{
"model": "not-found",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
},
{
"model": "ddebd",
"year": 1995
},
{
"model": "odq76",
"year": 1999
}
];
const items = [
{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
];
const transformed = models.reduce((res, val) => {
res[val.model] = val;
return res;
}, {}); // Transform models into a dictionary.
const filtered = items.filter(i => i.model in transformed);
console.log(filtered);
You could do this:
I thought you wanted to add the year from models
array too.
If so, look at this implementation. This is more efficient O(n)
than O(n*n)
solution that you attempted earlier. For large arrays O(n*n)
is not preferred.
let items = [{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
];
let models = [
{
"model": "ruie9",
"year": 1998
},
{
"model": "ooc0d",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
}
];
let objModels = models.reduce(function(r,v) {
r[v.model] = v;
return r;
}, {});
let objItems = items.reduce(function(r,v) {
r[v.model] = v;
return r;
}, {});
let ans = [];
for(let key in objItems) {
if(key in objModels) {
let o = objItems[key];
o.year = objModels[key].year;
ans.push(o);
}
}
console.log(ans);
You can rewrite
let obj = {
...items[j],
year: models[i].year
}
as
let obj = Object.assign({}, items[j], { year: models[i].year });
And you can also use Array.prototype.forEach
instead of a for
loop, like so
models.forEach((m) => {
items.forEach((i) => {
if (m.id === i.id) {
let obj = Object.assign({}, i, { year: m.year });
newArray.push(obj);
}
})
})
I tried to keep it as similar to your solution as possible.
Try this snippet:
const jsonData = {
"items": [{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
],
"models": [{
"model": "ruie9",
"year": 1998
},
{
"model": "ooc0d",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
},
{
"model": "ddebd",
"year": 1995
},
{
"model": "odq76",
"year": 1999
}
]
};
var newArray = jsonData.models.reduce(
(acc, modelData) => {
let filteredItems = jsonData.items.filter(item => item.model === modelData.model);
if (filteredItems.length) {
acc.push(...filteredItems);
}
return acc;
}, [])
console.log(newArray);