0

I have an array of objects that looks like this:

const input = [
  {id: 3, value: 2},
  {id: 0, value: 3},
  {id: 2, value: 8},
  {id: 1, value: 5},
  {id: 0, value: 2},
  {id: 1, value: 6}
]

And I am trying to build an array of the maximum value by id, with id as index. For our example the desired output is the following:

const output = [ 3, 6, 8, 2 ]

I am also assuming that I know the number of unique ids ahead of time, and that they start at 0 and rise sequentially. My first whack at this was to .map() over the an empty array of the right length and build intermediate arrays with .filter() for each id, then use Math.max() on the filtered arrays.

const myAttempt = Array(4).map((_, index) => {
  const filtered = input.filter(item => item.id === index);
  return Math.max(filtered);
});

All I get out of this is:

myAttempt = [ 4 empty slots ];

I suspect I'm totally off-base with the Array(4) bit, and that the answer might involve .reduce(), but I never really got the hang of reduce so any help would be very much appreciated.

PS: I'd prefer answers that avoid the use of libraries in the vein of lodash or jQuery.

borrascador
  • 575
  • 1
  • 5
  • 13
  • The idea is good, you're missing `.map(item => item.value)` though before passing into `Math.max`. Also `Math.max` takes multiple arguments not an array, so use spread syntax. – Bergi Sep 25 '18 at 21:51
  • Use `Array.from({length: 4}, (_, index) => …)` – Bergi Sep 25 '18 at 21:52
  • Aha, thanks for the clarifications and the link to the other question. I definitely got too caught up in the new Array / map weirdness to think through the rest! – borrascador Sep 25 '18 at 21:54

1 Answers1

1

Use Array.reduce() to collect the values highest value of each key. Convert to array using Array.values():

const input = [
  {id: 3, value: 2},
  {id: 0, value: 3},
  {id: 2, value: 8},
  {id: 1, value: 5},
  {id: 0, value: 2},
  {id: 1, value: 6}
]


const result = Object.values(input.reduce((r, { id, value }) => {
  r[id] = +r[id] > value ? r[id] : value;
  
  return r;
}, {}));

console.log(result);

If all ids from 0 on wards appear in the array, you can add the values by their id (index) to an array accumulator:

const input = [
  {id: 3, value: 2},
  {id: 0, value: 3},
  {id: 2, value: 8},
  {id: 1, value: 5},
  {id: 0, value: 2},
  {id: 1, value: 6}
]


const result = input.reduce((r, { id, value }) => {
  r[id] = +r[id] > value ? r[id] : value;
  
  return r;
}, []);

console.log(result);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • Thanks for showing me how to do it this way! Will accept as soon as time expires – borrascador Sep 25 '18 at 21:57
  • "*Convert to array using `Array.values()`*" - no, just start off with an `[]` as the accumulator – Bergi Sep 25 '18 at 21:58
  • That would potentially create an array with holes (for example not all ids are there) while `Object.values()` won't. – Ori Drori Sep 25 '18 at 22:03
  • I'm confused again. Where is `Array.values()` in this solution, and how would I use the accumulator like you said? – borrascador Sep 25 '18 at 22:04
  • I noticed that if I run `input.reduce` without `Object.values` around it, the answer becomes `{ 0: 3, 1: 6, 2: 8, id: 3, value: 2 }`, is this expected? – borrascador Sep 25 '18 at 22:05
  • Indeed. I'm create an object, and then extract it's values to an array using `Object.values()`. I've added the array accumulator solution. – Ori Drori Sep 25 '18 at 22:08