0

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.

6
  • Please visit the help center, take the tour to see what and How to Ask. Do some research, search for related topics on SO; if you get stuck, post a minimal reproducible example of your attempt, noting input and expected output. Commented Sep 4, 2018 at 14:37
  • @mplungjan fixed the typo in equal sign... i need an authoratitive answer to see what is the fastest way to do it. Commented Sep 4, 2018 at 14:43
  • That is off topic here. Codereview perhaps Commented Sep 4, 2018 at 14:45
  • @mplungjan ok close it plz, gonna move it to codereview Commented Sep 4, 2018 at 14:48
  • @mplungjan No! "the current is not returning what i want" means the code is not working as expected which is one close reason on Code Review. Commented Sep 4, 2018 at 14:50

5 Answers 5

3

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);
Sign up to request clarification or add additional context in comments.

2 Comments

Not come across array.has can't find any documentation either.
1

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)

3 Comments

is this the fastest way to do it? filter/find/reduce/ can't they be faster?
@storis you have array of objects inside the object which will surely have O(n2) complexity
i updated the question with an annex, could you please have a look at it? how can I achieve the similar results in this case?
1

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)

Comments

0

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)    

1 Comment

No longer a typo-type question but still off topic
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.