简体   繁体   中英

javascript extract objects from nested arrays using a list of ids

I have a list of ids as reference, and I have an object which contains multiple objects that have array of objects.

I want to make an array of objects with corresponding ids in the list, the FASTEST way.

 const data = { "items": { "item1": [{ "id": "id1", "info": "info1" }, { "id": "id2", "info": "info22" } ], "item20": [{ "id": "id3", "info": "info5" }], "item5": [{ "id": "id4", "info": "info6" }, { "id": "id5", "info": "info7" } ] } }; const keep = ['id4', 'id2']; const results = []; keep.forEach(function(val) { const match = Object.keys(data.items).map(item => { return data.items[item].find(obj => obj.id === val) }); results.push(match) }) console.log('final: ', results) 

the current is not returning what i want. the expected result will be:

[
    {
      "id": "id2",
      "info": "info22"
    },
    {
        "id": "id4",
        "info": "info6"
    }
]

update:

How about in the case if the data is itself an array of objects, and we want to do the same for each one?

  const data = [{ "otherStuff": "otherB", "items": { "item1": [{ "id": "id1", "info": "info1" }, { "id": "id2", "info": "info22" } ], "item20": [{ "id": "id3", "info": "info5" }], "item5": [{ "id": "id4", "info": "info6" }, { "id": "id5", "info": "info7" } ] } }, { "otherStuff": "otherA", "items": { "item1": [{ "id": "id1", "info": "info10000" }, { "id": "id2", "info": "info220000" } ], "item20": [{ "id": "id3", "info": "info5000" }], "item5": [{ "id": "id4", "info": "info60000" }, { "id": "id5", "info": "info7000" } ] } }]; const keep = ['id4', 'id2']; const results = []; keep.forEach(function(val) { data.forEach(function(entry){ Object.keys(entry.items).forEach(item => { var match = entry.items[item].find(obj => obj.id === val); if (match) { results.push(match) } }); }); }) console.log(results) 

and the output should be:

[
    {
        "otherStuff": "otherB",
        "items": [
                {
                      "id": "id2",
                      "info": "info22"
                },
                {
                    "id": "id4",
                    "info": "info6"
            }
        ]
    },
    {
        "otherStuff": "otherA",
        "items": [
                {
                      "id": "id2",
                      "info": "info220000"
                },
                {
                    "id": "id4",
                    "info": "info60000"
            }
        ]
    }
]

the result is not the same though.

If you use a Set for the kept ids, you save one O(n) traversal:

 const keep = new Set(['id4', 'id2']);

 const result = [];

 for(const items of Object.values(data.items))
   for(const item of items)
     if(keep.has(item.id))
       result.push(item);

You do not need to use map() . Simply use forEach() loop on the object keys which you want to keep and find the matching object so that it can be pushed into the result array.

 const data = { "items": { "item1": [{ "id": "id1", "info": "info1" }, { "id": "id2", "info": "info22" } ], "item20": [{ "id": "id3", "info": "info5" }], "item5": [{ "id": "id4", "info": "info6" }, { "id": "id5", "info": "info7" } ] } }; const keep = ['id4', 'id2']; const results = []; keep.forEach(function(val) { Object.keys(data.items).forEach(item => { var match = data.items[item].find(obj => obj.id === val); if (match) { results.push(match) } }); }) console.log('final: ', results) 

items is an object & item1 , item20 are are keys.So you can do Object.values and apply reduce function on it to get a single array which is consist of all the objects. No iterate the keep array and filter out the required element from the single array.

 const data = { "items": { "item1": [{ "id": "id1", "info": "info1" }, { "id": "id2", "info": "info22" } ], "item20": [{ "id": "id3", "info": "info5" }], "item5": [{ "id": "id4", "info": "info6" }, { "id": "id5", "info": "info7" } ] } }; const keep = ['id4', 'id2']; let getAllObjectValues = Object.values(data.items).reduce(function(acc, curr) { curr.forEach((elem) => { acc.push(elem) }) return acc; }, []); let k = keep.map(function(item) { return getAllObjectValues.filter(function(val) { return item === val.id })[0] }) console.log(k) 

You've used an assignment operator rather than an equivalence operator in your map function, change to:

const keep = ['id4', 'id2'];
const results = [];
keep.forEach(function(val){
    const match = Object.keys(data.items).map(item => {
        return data.items[item].find(obj => obj.id === val)
    });
    results.push(match)
})
console.log('final: ', results)    

Using a combination of reduce and filter you can iterate each sub-array checking whether the value should be kept.

 const data = { "items": { "item1": [ { "id": "id1", "info": "info1" }, { "id": "id2", "info": "info22" } ], "item20": [ { "id": "id3", "info": "info5" } ], "item5": [ { "id": "id4", "info": "info6" }, { "id": "id5", "info": "info7" } ] } }; const keep = ['id4', 'id2']; const filter = el => { return keep.indexOf(el.id) >= 0; }; const reducer = (accumulator, currentValue) => { return accumulator = accumulator.concat(data.items[currentValue].filter(filter)); }; let results = Object.keys(data.items).reduce(reducer, []); console.log('final: ', results); 

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