3

I have an array that I need to find the highest value of so when I apply it to a Highchart I can color the background if it exceeds some dynamic number a user inputs.

My code looks like this:

<div id="highest"></div>

var array = {
    data: [123, 234, 456, 789],
    data: [321, 654, 987],
    data: [963, 852, 741]
};

for (var i=0; i < array.data.length; i++){
    var m = Math.max.apply(Math, array.data);
    $('#highest').append('<div>'+m+'</div>');
}

all I get is the number

<div>963</div>
<div>963</div>
<div>963</div>
5
  • Don't you think it's weird that you're looping, but aren't doing anything with i? Use for in to loop over an object. And give unique keys Commented May 22, 2013 at 22:00
  • i is being used in the looping condition, so it's not quite doing nothing Commented May 22, 2013 at 22:01
  • 2
    Did you think it weird that your obects keys are all the same, overwriting each other -> Fiddle Commented May 22, 2013 at 22:01
  • yeah but it tells me I'm wrong no matter where I stick the i - I must be having an early case of Friday because I can't wrap my head around this Commented May 22, 2013 at 22:02
  • BTW, you don't need to supply the Math function as this, you can just use null. Commented May 22, 2013 at 23:58

6 Answers 6

4

Your array variable isn't an array([]), it is an object({}). You have multiple items in the object with the key data, but only one value per key is allowed.

So you have essentially written this:

var array = {
  data: [963, 852, 741]
};

Maybe you want something like this?

var array = [
  {data: [123, 234, 456, 789]},
  {data: [321, 654, 987]},
  {data: [963, 852, 741]}
];

var values = [];
for (var i=1; i < array.length; i++) {
  values.push.apply(values, array[i].data);
}
$('#highest').append('<div>' + Math.max.apply(Math, values) + '</div>');

or get rid of data entirely and just make it an array of arrays.

Sign up to request clarification or add additional context in comments.

1 Comment

ok - when I applied your answer to my actual source array it actually worked - haha - go figure it was what I originally tried but my example array is wrong.
4

First make a proper nested array set. Then you can use .map() to do this:

var array = [
    [123, 234, 456, 789],
    [321, 654, 987],
    [963, 852, 741]
];

var maxVals = array.map(function(a) {
    return Math.max.apply(Math, a);
});

Or like this:

var maxVals = array.map(Function.apply.bind(Math.max, Math));

3 Comments

That is so weird you posted this. I was literally about to make an answer. I've been trying to figure out how to do it the second way you have, and came up with the same thing. jsfiddle.net/SW7Ym . So weird.
Quick question - is there a reason you used Function.apply instead of Function.prototype.apply? I've always wondered, because I've seen people use Array.whatever instead of Array.prototype.whatever
@Ian: Just a quicker way to get to it. Since Function is a function, we don't need to go to the prototype. We could use isNaN.apply if we wanted. When people do Array.whatever, they're using a Firefox feature that can be easily shimmed in other browsers.
2

Well, that's not an array, it's an object with duplicated keys so you're just looping the last one that overrides all others.

Try this http://jsbin.com/olahuq/2/edit

var obj = {
  a: [123, 234, 456, 789],
  b: [321, 654, 987],
  c: [963, 852, 741]
};

var max = [];
for (var i in obj) {
  max.push(Math.max.apply(0, obj[i]));
}

$('#highest').append('<div>'+ max.join('</div><div>') +'<div>');

Altough you could just use an array of objects.

2 Comments

unfortunately, I can't change the data object - it comes from a json dynamically generated by the server
Then I'd suggest you track the problem on the server and fix it there before going any further. Duplicated keys are wrong, by definition a key must be unique.
1

Not sure what you're trying to do here. That "array" variable is defined as an object. Object literals in JavaScript need unique keys. Your last array keyed by "data" in the "array" object is the only one that the interpreter picks up.

You might want this?

var data = [
  [123, 234, 456, 789],
  [321, 654, 987],
  [963, 852, 741]
];

for (var i=0; i < data.length; i++){
  var m = Math.max.apply(Math, data[i]);
  $('#highest').append('<div>'+m+'</div>');
}

Comments

0

You are using multiple keys with the same name, which isn't valid JavaScript (well, the code may still run, but you won't get the results you're expecting). This is easy to fix, though—just use an array instead:

var arr = [
    [123, 234, 456, 789],
    [321, 654, 987],
    [963, 852, 741]
];

for (var i=0; i < arr.length; i++){
    var m = Math.max.apply(Math, arr[i]);
    $('#highest').append('<div>'+m+'</div>');
}

You could do this with an object, but I don't see any reason to, unless you're reading this data from a service or something and can't change its format.

2 Comments

anyone want to explain the downvote? i try to address the spirit of the question, not give literal answers for every question asked.
you are [ containing [ in an array
0

I just want to add another even more reduced way.

var obj = {
  a: [123, 234, 456, 789],
  b: [321, 654, 987],
  c: [963, 852, 741]
};
var max = Math.max.apply(0, [].concat.apply([], Object.values(obj)));

This however might be to obfuscated to be used in production code, I'd rather use reduce instead for better readability.

var max = Object.values(obj)
      .reduce((a, d) => a.concat(d), [])
      .reduce((p, c) => Math.max(p, c));

Finally you can also replace the latter reduce with a sort method:

var max = Object.values(obj)
      .reduce((a, d) => a.concat(d), [])
      .sort((l, r) => l - r)
      .pop();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.