1

I have the following object:

var questions = [{
    'question_id': 245,
    'question': 'Question 1',
    'ordinal': 1,
    'master_difficulty': 1,
    'overridden_difficulty': ''
},{
    'question_id': 34,
    'question': 'Question 2',
    'ordinal': 2,
    'master_difficulty': 1,
    'overridden_difficulty': ''
},{
    'question_id': 656,
    'question': 'Question 3',
    'ordinal': 3,
    'master_difficulty': 1,
    'overridden_difficulty': ''
},{
    'question_id': 86,
    'question': 'Question 4',
    'ordinal': 4,
    'master_difficulty': 1,
    'overridden_difficulty': ''
}]

And I want to get the highest ordinal value from it.

e.g. var highestOrdinal = highestOrdinalFunction(questions);

Where highestOrdinalFunction will return the highest ordinal number.

So in this case it would return 4.

Could Math.max work for this?

Cameron
  • 27,963
  • 100
  • 281
  • 483

4 Answers4

4

Array#reduce (spec | MDN) is the idiomatic way to do things like this:

function highestOrdinalFunction() {
    return questions.reduce(function(previous, entry) {
        return previous === undefined || entry.ordinal > previous ? entry.ordinal : previous;
    }, undefined);
}

Array#reduce calls a callback repeatedly, passing in the callback's previous return value, which is seeded with the second argument to reduce. That thing is usually called the "accumulator" for the reduce operation. The result of reduce is the final value of the accumulator.

The above will return undefined if questions is empty.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

I guess this is what you are looking for:

Math.max.apply(Math,questions.map(function(ques){return ques.ordinal;}))

please refer to Array.prototype.map for more info on how map() works.

invincibleDudess
  • 1,762
  • 2
  • 11
  • 18
0

We can just sort the objects within that array by the ordinal value and then return the first entry.

function highestOrdinalFunction( questions ) {
    return questions.sort( ( a, b ) => a.ordinal - b.ordinal )[ 0 ].ordinal;
}

It's probably a better idea to combine Array.prototype.map alongside Math.max() in this instance:

Math.max.apply( null, questions.map(q => q.ordinal) );
jAndy
  • 231,737
  • 57
  • 305
  • 359
0

You can find the max value two ways. You can either pass a function to map the property's value or call the property directly on the item. The result of these would be the mapped value to be applied the the Math.max calculation, in respect to the list of items.

Math.prototype.max

var questions = [
  {'question_id':245,'question':'Question 1','ordinal':1,'master_difficulty':1,'overridden_difficulty':''},
  {'question_id':34,'question':'Question 2','ordinal':2,'master_difficulty':1,'overridden_difficulty':''},
  {'question_id':656,'question':'Question 3','ordinal':3,'master_difficulty':1,'overridden_difficulty':''},
  {'question_id':86,'question':'Question 4','ordinal':4,'master_difficulty':1,'overridden_difficulty':''}
]

document.body.innerHTML =  'Via Function: ' + highestOrdinalValueFn(questions) + '\n';
document.body.innerHTML += 'Via Property: ' + highestOrdinalValueProp(questions);

// #1 : Via function
function highestOrdinalValueFn(items) {
  return max(items, function() {
    return this.ordinal;
  });
}
// #2 : Via property
function highestOrdinalValueProp(items) {
  return max(items, 'ordinal');
}

function max(list, prop) {
  return Math.max.apply(Math, list.map(function(item) {
    return isFunction(prop) ? prop.call(item) : item[prop];
  }));
}

function isFunction(fn) {
  return fn && {}.toString.call(fn) === '[object Function]';
}
body { white-space: pre; font-family: monospace; }

Array.prototype.reduce

var questions = [
  {'question_id':245,'question':'Question 1','ordinal':1,'master_difficulty':1,'overridden_difficulty':''},
  {'question_id':34,'question':'Question 2','ordinal':2,'master_difficulty':1,'overridden_difficulty':''},
  {'question_id':656,'question':'Question 3','ordinal':3,'master_difficulty':1,'overridden_difficulty':''},
  {'question_id':86,'question':'Question 4','ordinal':4,'master_difficulty':1,'overridden_difficulty':''}
]

document.body.innerHTML = highestValue(questions, 'ordinal');

function highestValue(items, prop) {
  return compare(items, function(curr, prev) {
    return maxNumericComparator(curr, prev, prop);
  })[prop];
}

function maxNumericComparator(curr, prev, prop) {
  if (curr && !prev) return -1;
  if (!curr && prev) return 1;
  if (curr[prop] && !prev[prop]) return -1;
  if (!curr[prop] && prev[prop]) return 1;
  if (curr[prop] > prev[prop]) return -1;
  if (curr[prop] < prev[prop]) return 1;
  return 0;
};

function compare(list, comparator) {
  return list.reduce(function(max, item) {
    return comparator(item, max) < 0 ? item : max;
  }, null);
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132