简体   繁体   中英

Filter nested JSON object with multiple arrays and store the filtered objects in an array

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM