Javascript中reduce方法的奇怪行为

时间:2018-01-25 13:50:35

标签: javascript arrays

任何人都可以向我解释这种情况吗?

在第二次调用函数时,结果为{cat: 2, cat,cat: 1, dog: 1, frog: 1}

但是,我认为结果将是{cat: 4, dog: 1, frog: 1}

这里发生了什么?

var animals = ['cat', 'cat', ['cat'], 'dog', 'frog'];

var otherAnimals = ['cat', 'cat', ['cat', 'cat'], 'dog', 'frog'];

function reducingArrays(arraySource) {
  var countedData = arraySource.reduce(function(allItems, item) {
    if (item in allItems) {
      allItems[item]++;
    } else {
      allItems[item] = 1;
    }
    return allItems;
  }, {});

  console.log(countedData);
}

reducingArrays(animals); // {cat: 3, dog: 1, frog: 1}

reducingArrays(otherAnimals); // {cat: 2, cat,cat: 1, dog: 1, frog: 1}
// What I expected: {cat: 4, dog: 1, frog: 1}

5 个答案:

答案 0 :(得分:1)

您可以将单个元素转换为数组:



var animals = ['cat', 'cat', ['cat'], 'dog', 'frog'];

var otherAnimals = ['cat', 'cat', ['cat', 'cat'], 'dog', 'frog'];

function reducingArrays(arraySource) {
  var countedData = arraySource.reduce(function(allItems, item) {
    var arr = Array.isArray(item) ? item : [item];
    allItems[arr[0]] = (allItems[arr[0]] || 0) + arr.length;
    return allItems;
  }, {});

  console.log(countedData);
}

reducingArrays(animals);

reducingArrays(otherAnimals); 




答案 1 :(得分:0)

如果其中一个对象是数组,则必须处理:

function reducingArrays(arraySource){
    var countedData = arraySource.reduce(function (allItems, item) {
        var items = [item];
        if(item.constructor === Array){
            items = item;
        }
        items.forEach(function(item){
            if (item in allItems) {
                allItems[item]++;
            } else {
                allItems[item] = 1;
            }               
        });
        return allItems;
    }, {});
    console.log(countedData);
}

答案 2 :(得分:0)

Yoh可以使用对数组的检查,并对嵌套数组使用reduce的相同回调。



function reducingArrays(arraySource) {
    return arraySource.reduce(function iter(allItems, item) {
        if (Array.isArray(item)) {
            return item.reduce(iter, allItems);
        }
        allItems[item] = (allItems[item] || 0) +1;
        return allItems;
    }, {});
}


var animals = ['cat', 'cat', ['cat'], 'dog', 'frog'];
var otherAnimals = ['cat', 'cat', ['cat', 'cat'], 'dog', 'frog'];

console.log(reducingArrays(animals));      // { cat: 3, dog: 1, frog: 1}
console.log(reducingArrays(otherAnimals)); // { cat: 4, dog: 1, frog: 1 }




答案 3 :(得分:0)

第一条评论已经解释过,这与数组的字符串化有关,因为对象键只能是字符串。

这是一种如何在函数中处理嵌套数组的方法。

function countAnimals(source) {
  function _count(allItems, item) {
    if (Array.isArray(item)) {
      return item.reduce(_count, acc);
    }

    if (item in allItems) {
      allItems[item]++;
    } else {
      allItems[item] = 1;
    }
    return acc;
  }

  //needs `source` to be an Array
  return source.reduce(_count, {});

  //this would also work, if `source` is a single animal.
  //like countAnimals('dog');
  //I prefer this approach because it is more flexible 
  //on what the function can deal with, 
  //and it doesn't cost me even a single extra line of code
  //return _count({}, source);
}


var animals = ['cat', 'cat', ['cat'], 'dog', 'frog'];
console.log("simple", countAnimals(animals));

var otherAnimals = ['cat', 'cat', ['cat', 'cat'], 'dog', 'frog'];
console.log("nested", countAnimals(otherAnimals));

//and a deeply nested structure
var moreAnimals = ['mouse', ['cat', ['dog', 'duck', ['frog']], 'cat'], 'dog', 'frog'];
console.log("multiple levels", countAnimals(moreAnimals));
.as-console-wrapper{top: 0;max-height: 100%!important}

答案 4 :(得分:0)

如果您的数组只是嵌套一层,您可以使用[].concat(...arr)展平它,然后再使用reduce进行迭代。

在这个例子中,我也使条件更简洁。



var animals = ['cat', 'cat', ['cat'], 'dog', 'frog'];
var otherAnimals = ['cat', 'cat', ['cat', 'cat'], 'dog', 'frog'];

function reducingArrays(arraySource) {
  return [].concat(...arraySource).reduce(function(allItems, item) {
    allItems[item] = allItems[item] || 0;
    allItems[item]++;
    return allItems;
  }, {});
}

const result = reducingArrays(animals);
const result2 = reducingArrays(otherAnimals);

console.log(result);
console.log(result2);