JavaScript: создайте функцию groupBy, которая принимает массив и обратный вызов и возвращает объект - PullRequest
0 голосов
/ 11 июня 2019

Моя цель такова:

Создать функцию groupBy, которая принимает массив и обратный вызов и возвращает объект.groupBy будет перебирать массив и выполнять обратный вызов для каждого элемента.Каждое возвращаемое значение из обратного вызова будет сохранено как ключ на объекте.Значение, связанное с каждым ключом, будет массивом, состоящим из всех элементов, которые привели к тому возвращаемому значению при передаче в обратный вызов.

Код ниже успешно выполняется:

function groupBy(array, inputFunc) {
    let obj = {};

  for(let i of array){
    let key = inputFunc(i);

    // QUESTION on line of code below: 
    console.log(obj[key])

    if(obj[key] === undefined){
      obj[key] = [];
    }
        obj[key].push(i)
  }
  return obj; 
}

// Uncomment these to check your work!
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] }

Но яЯ немного запутался в коде.В частности, когда я делаю:

console.log(obj[key])

, кажется, что вышеприведенная строка кода возвращает:

undefined
undefined
[ 2.1 ]
undefined

Почему печать не определена?Откуда это?

Поскольку я не понимаю, откуда исходит неопределенное, я не понимаю, зачем нужно утверждение if.

Ответы [ 2 ]

0 голосов
/ 11 июня 2019

Потому что он показывает, существует ли элемент или нет. Если это не так, он переходит к оператору if. Поставьте console.log после оператора if, чтобы удалить все undefined.

function groupBy(array, inputFunc) {
  let obj = {};
  for (let i of array) {
    let key = inputFunc(i);
    if (obj[key] === undefined) {
      obj[key] = [];
    }
    console.log(obj[key]);
    obj[key].push(i);
  }
  return obj;
}

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

console.log(groupBy(decimals, floored));
.as-console-wrapper { max-height: 100% !important; top: auto; }

Обратите внимание, что в этом нет необходимости - если все, что вам нужно, это obj, возвращаемый функцией:

function groupBy(array, inputFunc) {
  let obj = {};
  for (let i of array) {
    let key = inputFunc(i);
    if (obj[key] === undefined) {
      obj[key] = [];
    }
    obj[key].push(i);
  }
  return obj;
}

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

console.log(groupBy(decimals, floored));
.as-console-wrapper { max-height: 100% !important; top: auto; }
0 голосов
/ 11 июня 2019

Когда вы делаете

console.log(obj[key])

, вы не знаете, имеет ли объект указанный ключ или нет;в конце концов, только после можно присвоить массив этому ключу, если нет связанного значения:

if(obj[key] === undefined){
  obj[key] = [];
}

Итак, на каждой итерации, если ключ, который повторяется, имеетеще не был помещен в объект, он будет регистрировать undefined, и позже на той же итерации этому ключу объекта будет присвоен пустой массив.

Например, на первой итерации i равно 1.3, поэтому сгенерированный ключ равен let key = inputFunc(i); -> let key = inputFunc(1.3); -> let key = 1.Но объект начинается без ключей вообще, поэтому

obj[1]

оценивается как undefined, более поздний оператор if обнаруживает это и назначает массив этому ключу:

if(obj[key] === undefined){
  obj[key] = [];
}

на первой итерации разрешается в

if(obj[1] === undefined){
  obj[1] = [];
}
// ->
if(undefined === undefined){
  obj[1] = [];
}

Вы также можете рассмотреть возможность использования reduce, что более функционально и, возможно, более уместно при преобразовании массива в единственное значение:

const groupBy = (array, inputFunc) => array.reduce((a, elm) => {
  const key = inputFunc(elm);
  if (!a[key]) {
    a[key] = [];
  }
  a[key].push(elm);
  return a;
}, {});

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] }
...