Emilio
Emilio

Reputation: 2109

Weird Behavior Pushing Into Array Stored in a JavaScript Object's Value

Inside of the else clause, the commented out line gives the desired result, but the one below it causes { '1': [ 1.3 ], '2': [ 2.1 ] } to become { '1': [ 1.3 ], '2': 2 }. I don't understand why this is happening.

const groupBy = (array, callback) => {
  let obj = {}
  for (let i = 0; i < array.length; i++) {
    let currKey = callback(array[i])
    let newVal = array[i]
    let currVal = obj[currKey]
    if (!currVal) {
        obj[currKey] = [newVal]
    } else {
        // obj[currKey].push(newVal)
        obj[currKey] = currVal.push(newVal)
    }
  } 
  return obj
} 

// Uncomment these to check your work!
var decimals = [1.3, 2.1, 2.4]
var floored = function(num) { return Math.floor(num) }
groupBy(decimals, floored); // expect { 1: [1.3], 2: [2.1, 2.4] }

Upvotes: 1

Views: 118

Answers (1)

bcr
bcr

Reputation: 3811

Array.prototype.push does not return a new array, it returns the length of the array.

const groupBy = (array, callback) => {
  // let arrayValues = [] // this isn't used anywhere
  let obj = {}
  for (let i = 0; i < array.length; i++) {
    let currKey = callback(array[i])
    let newVal = array[i]
    let currVal = obj[currKey]
    if (!currVal) {
        obj[currKey] = [newVal]
    } else {
        obj[currKey].push(newVal) // this should work instead
        //obj[currKey] = currVal.push(newVal)
    }
  } 
  return obj
}

Since arrays are a reference type you just need to push your new item into the array obj[currKey].push(newValue) without setting obj[currKey] again. You're pushing a new value into that array where it lives in memory so no need to re-assign it to anything. You can see how lodash does that here (although you'll have to untangle some helper functions).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

Upvotes: 3

Related Questions