Search code examples
javascriptarraysmethods

set array element object property based on the presence of an element of another array with the same id using array methods


The title is very wordy, so I will demonstrate the idea with an example and a working code:

Consider a large song library available in a store. Lets call it "bigarray". A client has his/her own personal library of purchased songs from that store: "smallArray". BigArray elements has a property "purchased". I need to set that property to "true" if there is a match by id between songs of both arrays. A working code example:

for (let i = 0; i < bigArray.length; i++) {
  for (let j = 0; j < smallArray.length; j++) {
    if (bigArray[i].id === smallArray[j].id) {
      bigArray[i].purchased = true;
    }
  }
}

Is there a way to program that using array methods like map, filter etc. with predicate functions possibly in one line, instead of a double for loop?


Solution

  • You could first create a set of ids from the objects in your smallArray, then use .map() on your bigArray to update the purchased property to true or false based on whether the set has the id of the current object from the big array:

    const smallSet = new Set(smallArray.map(({id}) => id));
    const result = bigArray.map(obj => ({...obj, purchased: smallSet.has(obj.id)}));
    

    You could also use .some() to determine if your smallArray has an object that matches an id from your bigArray, this has a worse time-complexity of O(n*k) compared to using the set which is O(n+k), but is more suitable for a "one-liner" if that's what you're after:

    const result = bigArray.map(obj => ({
      ...obj, 
      purchased: smallArray.some(item => item.id === obj.id)
    }));
    

    Both of these create new object references for each object in the new array, even if you're not updating the purchased property. To create new objects just for the object you're updating, you can use the result of .has() or .some() as the conditional operand like so:

    bigArray.map(obj => smallSet.has(obj.id) ? {...obj, purchased: true} : obj);