6

So I have data like this:

data = [
         [{a: "b", value: 12}, {a: "bb", value: 39}, {a: "bb", value: 150}],
         [{a: "c", value: 15}, {a: "cc", value: 83}, {a: "ccc", value: 12}],
         [{a: "d", value: 55}, {a: "dd", value: 9}, {a: "dd", value: 1}]
       ]

I want to get max values of value in each array of objects. So the result should be like this:

maxValues = [150, 83, 55]

Right now my code is:

let maxValues = []
let tmp;
let highest = Number.NEGATIVE_INFINITY;

data.map((eachArr, index) => {
  for(let i = eachArr.length -1; i >= 0; i--){
    tmp = eachArr[i].value;
    if(tmp > highest) highest = tmp;
  }
  maxValues.push(highest)
})

and the result is

maxValues = [150, 150, 150]

How can I achieve this?

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
kay
  • 1,369
  • 4
  • 15
  • 27
  • 5
    Are the syntax errors (no closing `}` character for each of the objects) present in your real code, or is that a typo here? – David Thomas Jan 23 '17 at 08:43
  • `data = [ [{a: "b", value: 12}, {a: "bb", value: 39, {a: "bb", value: 150], [{a: "c", value: 15}, {a: "cc", value: 83, {a: "ccc", value: 12], [{a: "d", value: 55}, {a: "dd", value: 9, {a: "dd", value: 1] ]` not in right format, please have a look – Pranav Patel Jan 23 '17 at 08:44
  • 1
    Seems like a Typo ... I suggested an edit ... If not, then the user has bigger problems ! – Exception_al Jan 23 '17 at 08:44
  • 2
    @Addy: I saw, and rejected, that edit: please don't 'correct' code in a question (unless the OP specifically confirms a given typo), in many instances the typo can be the problem, and changing, or correcting, the code then hides the reason for the question being asked. (Also I rolled back the edit which, for some reason, was approved. Sorry, it really is nothing personal though.) – David Thomas Jan 23 '17 at 08:47
  • All clear ... shall keep that in mind. – Exception_al Jan 23 '17 at 08:47
  • @DavidThomas sorry. it was a typo. thanks for pointing it out – kay Jan 23 '17 at 11:47
  • @Addy Thank you for an edit, and it was a typo. thanks again. – kay Jan 23 '17 at 11:47

5 Answers5

20

You could use the spread syntax and take the max of mapped value.

The spread syntax allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables  (for destructuring assignment) are expected.

var data = [[{ a: "b", value: 12}, {a: "bb", value: 39 }, {a: "bb", value: 150 }], [{ a: "c", value: 15}, {a: "cc", value: 83 }, {a: "ccc", value: 12 }], [{ a: "d", value: 55}, {a: "dd", value: 9 }, {a: "dd", value: 1 }]],
    result = data.map(a => Math.max(...a.map(b => b.value)));

console.log(result);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 4
    I realise you've posted this recently, but could you take the time to explain what the code does, and how it works? That way, hopefully, it's of more use to future visitors. Beautifully written, by the way! :) – David Thomas Jan 23 '17 at 08:49
  • I would also appreciate an explanation .. that'd be like a cherry on top ... and save me the time googling how this works .-) – Exception_al Jan 23 '17 at 08:50
  • The spread operator `...` ain't hard to unnderstand, she includes the link, don't be lazy people :D – Trash Can Jan 23 '17 at 08:52
7

You have to include let highest = Number.NEGATIVE_INFINITY; inside forEach function, because you have to set highest from every set in your array.

data = [
         [{a: "b", value: 12}, {a: "bb", value: 39}, {a: "bb", value: 150}],
         [{a: "c", value: 15}, {a: "cc", value: 83}, {a: "ccc", value: 12}],
         [{a: "d", value: 55}, {a: "dd", value: 9}, {a: "dd", value: 1}]
       ]
let maxValues = []
let tmp;
data.forEach((eachArr, index) => {
  let highest = Number.NEGATIVE_INFINITY;
  for(let i = eachArr.length -1; i >= 0; i--){
    tmp = eachArr[i].value;
    if(tmp > highest) highest = tmp;
  }
  maxValues.push(highest)
})
console.log(maxValues);
Mihai Alexandru-Ionut
  • 47,092
  • 13
  • 101
  • 128
  • 1
    `map` is being abused here. The code should use `forEach`, or should actually use the result of `map` (e.g., `let maxValues = data.map(...);` where the callback returns `highest`). – T.J. Crowder Jan 23 '17 at 08:49
4

Ecmascript 5 solution with Math.max.apply() and Array.prototype.map() functions:

var data = [
    [{a: "b", value: 12}, {a: "bb", value: 39}, {a: "bb", value: 150}],
    [{a: "c", value: 15}, {a: "cc", value: 83}, {a: "ccc", value: 12}],
    [{a: "d", value: 55}, {a: "dd", value: 9}, {a: "dd", value: 1}]
];

var maxValues = data.map(function (arr) {
    return Math.max.apply(null, arr.map(function(o){ return o.value; }));
});

console.log(maxValues);

Math.max.apply() function will return the largest of the given numbers.
The numbers(value attribute of each nested object) are accumulated via Array.prototype.map() function.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max

RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
3

Iterate over the array using Array#map, to generate the array element find out an object which contains the largest value using Array#reduce and then retrieve its value property.

data.map(arr => arr.reduce((a, b) => a.value < b.value ? b : a).value)

data = [
  [{
    a: "b",
    value: 12
  }, {
    a: "bb",
    value: 39
  }, {
    a: "bb",
    value: 150
  }],
  [{
    a: "c",
    value: 15
  }, {
    a: "cc",
    value: 83
  }, {
    a: "ccc",
    value: 12
  }],
  [{
    a: "d",
    value: 55
  }, {
    a: "dd",
    value: 9
  }, {
    a: "dd",
    value: 1
  }]
]

console.log(
  data.map((arr) => arr.reduce((a, b) => a.value < b.value ? b : a).value)
)

Without ES6 arrow function :

data.map(function(arr){
  return arr.reduce(function(a, b){
    return a.value < b.value ? b : a
  }).value;
});
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
2

Using underscore max function

Whitout ES6

_(data).map( function (item){
   var max = _(item).max( function( hash ){ return hash.value })
   return max.value
});

With ES6

_(data).map((item) => _(item).max(( hash ) => hash.value).value);