0

I am attempting to create a function that takes an object and returns an array with the highest and lowest keys. My problem is the array does not have the highest value but instead the second highest value? My code is below and even when I add a second while value (another loop for max) it still comes up with the second highest value.

function minMaxKeyInObject(obj) {
  let newArr = [];
  let min;
  let max;
  for (let i in obj) {
    if (min === undefined || i < min) {
      min = i;
    }
    if (i > max){
      max = i;
    }
  }
  for (let j in obj) {
    // console.log(j)
    if (max === undefined || j > max) {
      max = j;
    }
  }
  newArr.unshift(max);
  newArr.unshift(min);
  return newArr;
}
let obj = { 1: 'Max', 2: 'Jim', 4: 'Leia', 11: 'Jacob', 7: 'Bob', 8: 'Kim', 3: 'Billy' }

I am having zero issues with the min value it's just the max.

I have tried changing the conditional, adding in a second conditional, a second loop, and switching the order but the results stay the same. Any help would be appreciated.

3 Answers3

1

As others have stated, object properties that represent integer index numbers are actually strings, and so comparing them will give the result of a string comparison.

If your object has only such index properties -- i.e. non-negative integers up to 232−1 in standard decimal representation -- then they will be iterated in numerical order (see also this). So you don't need any other logic than to get the first and last one:

let obj = { 2: 'Jim', 1: 'Max', 4: 'Leia', 11: 'Jacob', 7: 'Bob', 8: 'Kim', 3: 'Billy' }

let minmax = Object.keys(obj);
minmax = [+minmax[0], +minmax.pop()];

console.log(minmax);
trincot
  • 317,000
  • 35
  • 244
  • 286
0

Try using Object.keys and Math.[min/max] to determine the minimum and maximum value. Or sort the keys and return the first and last value of the result (minMax in the snippet).

The keys of an object are always String, so they must be converted to Number before you can use them as such. From MDN:

Object.keys() returns an array whose elements are strings corresponding to the enumerable properties found directly upon object

const obj = { 1: 'Max', 2: 'Jim', 4: 'Leia', 11: 'Jacob', 7: 'Bob', 8: 'Kim', 3: 'Billy' };
const keys = Object.keys(obj).map(Number);
console.log(JSON.stringify([Math.min.apply(null, keys), Math.max.apply(null, keys)]));
console.log(JSON.stringify(minMax(keys)));

function minMax(values) {
  const toNumber = values.map(Number);
  if (!toNumber.filter(v => isNaN(v)).length) {
    toNumber.sort( (a, b) => a-b );
    return [toNumber[0], toNumber.pop()];
  }
  return "Not all values are numbers";
}
KooiInc
  • 119,216
  • 31
  • 141
  • 177
0

Objects store their keys as strings or Symbols. As a result, when you iterate the keys of your object, your i will be a string and not a number. As you're comparing the string versions of your numbers, your comparison will give undesirable results. For example, when your code performs:

"11" > "4"

you get false, and so the max isn't updated. Instead, convert your key to a number first, and then compare.

You can also remove the second loop, as you're already finding the max in the first loop. It also might be easier for you to default your min/max to Infinity and -Infinity, so that when you compare any number against the default values they'll automatically take the new value:

function minMaxKeyInObject(obj) {
  let min = Infinity;
  let max = -Infinity;
  for (let i in obj) {
    let keyNum = Number(i);
    if (keyNum < min)
      min = keyNum;
      
    if (keyNum > max)
      max = keyNum;
  }
  return [min, max];
}

let obj = { 1: 'Max', 2: 'Jim', 4: 'Leia', 11: 'Jacob', 7: 'Bob', 8: 'Kim', 3: 'Billy' };
console.log(minMaxKeyInObject(obj));
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64