Javascript中reduce方法的奇怪行为

3

有人能向我解释一下这种情况吗?

在第二次调用该函数时,结果是{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}


8
['cat'] 转换为 'cat'['cat','cat'] 转换为 'cat,cat'。你正在使用数组作为对象键,因此将其转换为字符串。你需要一种递归函数。 - Niet the Dark Absol
5个回答

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); 


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);
}

0
你可以对数组进行检查,并在嵌套数组中使用相同的回调函数来使用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 }


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}


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);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接