1

I'm creating a function that accepts an array and a callback, and returns an object. It is designed to iterate through the array and perform the callback on each element. Then, each return value from the callback is saved as a key on the object. The value associated with each key will be an array consisting of all the elements that resulted in that return value when passed into the callback.

function groupBy(array, callback) {
  let obj = {};
  let newArr = [];
  //loop through each ele w/ callback
  //return value saved as key in obj obj[key] = value
  array.forEach(ele => {
    let key = callback(ele)
    obj[key] = callback(ele); 
    if (obj[key] === undefined) {
      obj[key] = array[ele]
      newArr.push(array[ele]);
        } else {
        newArr.push(obj[key]);
        }  
    });
  return obj;
}

The function should create arrays as values of the returned object but it doesn't. Also, it does not group array items together if the callback returns the same value when they are passed in.

Test cases(s):

const decimals = [1.3, 2.1, 2.4];
const floored = function(num) { return Math.floor(num); };
console.log(groupBy(decimals, floored)); // should log: **{ 1: [1.3], 2: [2.1, 2.4] }**

Instead I get: { 1: 1, 2: 2 }</be expected { odd: 'odd', even: 'even' } to deeply equal { odd: [ 1, 3, 5 ], even: [ 2, 4 ] }

1
  • this type of problem is already created in the javascript language, it is the array.reduce () method Commented Jul 7, 2020 at 11:54

3 Answers 3

1

There are more than 1 problem with your code.

First, you are using obj[key] = callback(ele) asignment which assigns key to object[key]

Second, you are pushing into the newArr array but never using it.

Snippet below might help you.

function groupBy(array, callback) {
  let obj = {};
  
  //loop through each ele w/ callback
  //return value saved as key in obj obj[key] = value
  array.forEach(ele => {
    let key = callback(ele)
    obj[key] = obj[key] || [];
    //                  ^^^^ Create an empty array if it doesn't exist
    obj[key].push(ele)
  });
  return obj;
}

const decimals = [1.3, 2.1, 2.4];
const floored = function(num) {
  return Math.floor(num);
};
console.log(groupBy(decimals, floored)); // should log: **{ 1: [1.3], 2: [2.1, 2.4] }**


Update

You can also use Array.reduce()

function groupBy(array, callback) {

  return array.reduce((acc,cur) => {
    let key = callback(cur)
    acc[key] = acc[key] || [];
    acc[key].push(cur)
    return acc;
  },{})
  
}

const decimals = [1.3, 2.1, 2.4];

const floored = function(num) {
  return Math.floor(num);
};

console.log(groupBy(decimals, floored));

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

2 Comments

Thank you this is very helpful. Why shouldn't I use obj[key] = callback(ele) assignment which assigns key to object[key]?
You're welcome. Glad to hear it worked for you :) callback(ele) returns the key to store the actual value. For example, for the value 1.21 it returns 1. Therefore you assign it like object[1]=1 but you want object[1].push(1.21)
1
function groupBy(array, callback) {
  let obj = {};
  //loop through each ele w/ callback
  //return value saved as key in obj obj[key] = value
  array.forEach(ele => {
    let key = callback(ele)
    if (obj[key] === undefined) {
      obj[key] = [ele]
        } else {
        obj[key].push(ele);
        }  
    });
  return obj;
}

Comments

0

You should not override the key, instead you should get array and push it to the array.

function groupBy(array, callback) {
  let obj = {};
  let newArr = [];
  //loop through each ele w/ callback
  //return value saved as key in obj obj[key] = value
  array.forEach(ele => {
    let key = callback(ele)
    
    //obj[key] = key; 
    let newArr = obj[key];
    if (newArr === undefined) {
        newArr = new Array();
    }
    newArr.push(ele);
    obj[key] = newArr;
    });
  return obj;
}

const decimals = [1.3, 2.1, 2.4];
const floored = function(num) { return Math.floor(num); };
console.log(groupBy(decimals, floored));

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.