-5

I have the following array:

[0:{
boat: "Laura"
date: "2022-05-14"
doy: 133
end: "22:00:00"
fname: "David"
lname: "Cross"
skipperid: 217
spots: 5
start: "09:00:00"
type: "RES"},
1:{
boat: "Avrora"
date: "2022-05-14"
doy: 133
end: "13:00:00"
fname: "Bob"
lname: "Smith"
skipperid: 1
spots: 3
start: "10:00:00"
type: "SAIL"}]

I apply the following to turn it into an object of arrays where the keys to each object is the skipperid.

daySails = daySails.reduce((b, a) => ({        
           ...b,
           [a.skipperid]: a
           }), {});

could someone explain how this works?

DCR
  • 14,737
  • 12
  • 52
  • 115
  • [Using spread operator to update an object value](https://stackoverflow.com/q/49491393) | [How to use a variable for a key in a JavaScript object literal?](https://stackoverflow.com/q/2274242) | https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce – VLAZ Feb 04 '22 at 18:29
  • In this reduce unpacks b on each iteration, and a var which is current object in each iteration is being set dynamically and value is the current obj. – Parvesh Kumar Feb 04 '22 at 18:29
  • 2
    `reduce` isn’t complicated at all. It accepts two arguments: a callback and an initial aggregator. The aggregator is also the return value, the first argument of the callback, and the expected return value of the callback. The other arguments of the callback are the current value of the array, the current index, and the array itself. It’s `const finalAggregator = array.reduce((intermediateAggregator, currentValue, currentIndex, currentArray) => { /* Do the thing. */ return modifiedAggregator; }, initialAggregator);`. – Sebastian Simon Feb 04 '22 at 18:30

1 Answers1

3

I would write that differently to avoid creating a new object on each iteration, and also to make it less "complicated":

daySails = daySails.reduce((b, a) => {
  b[a.skipperid] = a;
  return b;
}, {});

Each iteration adds a new element to the result object, with the "skipperid" as its key. In each call to the => callback function, b is the object being built step-by-step (initialized with the {} in the .reduce() call), and a is an element of the source array (the original daySails). Thus each source element is added to the built-up result element by it's skipperid.

Note that if two entries in the original have the same skipperid, you'll end up with only one. The usual way to deal with that, if it's a problem you face, is to turn the entries into arrays instead of just single objects:

daySails = daySails.reduce((b, a) => {
  // Check if the "skipperid" is present already
  if (!b[a.skipperid])
    b[a.skipperid] = []; // nope, so create new array 
  b[a.skipperid].push(a); // add element
  return b;
}, {});
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • this is really helpful. could you add a little more explanation? what are b,a in each iteration. I assume the {} is just the initial value (an empty object) that we will be adding the return to – DCR Feb 04 '22 at 18:36
  • @DCR updated, I'm going to add a little more too. – Pointy Feb 04 '22 at 18:40
  • \@Pointy thank you. On the first iteration is b just the supplied initial value {}? and a is the first object in the array? neve rmind here, your explanation is perfect. – DCR Feb 04 '22 at 18:46