1

Set only adds 1 copy of an array and I'm not sure why it doesn't keep adding other copies.

The function below takes in an array of trips with the travelers id and another array containing the travelers' ids and names. In this chunk of code,

if(item.type === type){
      store.add(...item.travelers);
    }

I expected that 123,456 and 789 will be added to the set. However, only 123 and 456 are added. Why doesn't the Set add in the second copy (which would be 456 and 789)?

const travelers = [
  {
  id: 123,
  name: 'John'
  },
  {
  id: 456,
  name: 'Raymond'
  },
  {
  id: 789,
  name: 'Mary'
  },
];


const trip = [
  {
    type: 'car',
    travelers: [123, 456]
  },
  {
    type: 'flight',
    travelers: []
  },
  {
    type: 'car',
    travelers: [456, 789]
  },
];


function determinePeopleForEachTripType(arr, travelers, type){
  const result = [];
  let store = new Set();

  for(let i = 0; i< arr.length; i++){
    let item = arr[i];
    if(item.type === type){
      store.add(...item.travelers);
    }
  }

  store.forEach(eachStore =>{
    for(let j = 0; j< travelers.length; j++){
      if(eachStore === travelers[j].id){
        result.push(travelers[j].name)
      }
    }
  })

  return result;
}

determinePeopleForEachTripType(trip, travelers, 'car');

Expected result: Set contains [123, 456, 789]. But actual output is Set contains [123, 456]. What are some possible ways to fix this code?

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
bryanh210
  • 27
  • 2

2 Answers2

1

Set.prototype.add only takes one argument, and that's the one element - you need to iterate through travellers and add each item separately:

item.travelers.forEach(Set.prototype.add, store);
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
  • But I thought the spread operator was already for that? – bryanh210 Jun 23 '19 at 00:42
  • No, see the docs - unlike `push`, `add` only has one parameter, so can *only* add one item each time. That's why we need the loop. – Jack Bashford Jun 23 '19 at 00:43
  • I see. Could you help me understand why the Set then adds 123 and 456 when used with the spread operator? – bryanh210 Jun 23 '19 at 00:47
  • you have a travelers array with first element 123, and another with first element 456 - so that's why - change the second array to `travelers: [789, 456]` to see that *your code* would add 123 and 789 – Jaromanda X Jun 23 '19 at 00:50
  • 1
    You're doing the equivalent of `store.add(123, 456)` followed by `store.add(456, 789)`. The first statement add `123` to the list, and ignores the `456` parameter. The second adds `456` and ignores the `789` one, as `add` only cares about the first parameter. – Scott Sauyet Jun 23 '19 at 01:00
  • This doesn't work, you'd need to use `item.travelers.forEach(Set.prototype.add, store)` to have the right context – Bergi Jun 23 '19 at 21:52
  • Ok @Bergi, never to sure about these ones - I'll edit my answer. Is it due to the `this` context? – Jack Bashford Jun 24 '19 at 00:26
  • Yes, the `this` context of `add` – Bergi Jun 24 '19 at 04:21
0

const travelers = [
  {
  id: 123,
  name: 'John'
  },
  {
  id: 456,
  name: 'Raymond'
  },
  {
  id: 789,
  name: 'Mary'
  },
];


const trip = [
  {
    type: 'car',
    travelers: [123, 456]
  },
  {
    type: 'flight',
    travelers: []
  },
  {
    type: 'car',
    travelers: [456, 789]
  },
];


function determinePeopleForEachTripType(arr, travelers, type){
  const result = [];
  let store = new Set();

  for(let i = 0; i< arr.length; i++){
    let item = arr[i];
    if(item.type === type){
      for (let traveler of item.travelers) {
        store.add(traveler);
      }
    }
  }

  store.forEach(eachStore =>{
    for(let j = 0; j< travelers.length; j++){
      if(eachStore === travelers[j].id){
        result.push(travelers[j].name)
      }
    }
  })

  return result;
}

const result = determinePeopleForEachTripType(trip, travelers, 'car');

console.log(result)