Javascript reduce(),传入初始值

时间:2015-10-17 00:25:25

标签: javascript underscore.js

我正在使用下划线库进行练习,以执行项目出现次数。

具体来说,我有这个数组:

products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];

我正在尝试使用map(),flatten()和reduce()来确定每种成分出现的次数。

当我使用下面的代码时,ingredientCount返回未定义的值:

var ingredientCount = { "{ingredient name}": 0 };

    _(products).chain()
    .map(function(obj) {return obj.ingredients;})
    .flatten().reduce(function(memo, x) {
      return memo[x] = (memo[x] || 0) + 1;
    }, ingredientCount)
    .value();

但是,如果我删除第二个参数reduce()并在函数体中包含初始对象,那么一切都按预期工作,即:

var ingredientCount = {“{ingredient name}”:0};

_(products).chain()
.map(function(obj) {return obj.ingredients;})
.flatten().reduce(function(memo, x) {
  return ingredientCount[x] = (ingredientCount[x] || 0) + 1;
})
.value();

有人可以帮助解释为什么会这样吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

return memo[x] = (memo[x] || 0) + 1;返回循环的下一次迭代的数字以用作备忘录。

代替

memo[x] = (memo[x] || 0) + 1;
return memo;

如果你真的想要在一个声明中

return memo[x] = (memo[x] || 0) + 1, memo;

答案 1 :(得分:1)

看到简单的JS替代方案总是很有趣:

var counts = p.reduce(function(acc, prod) {
  prod.ingredients.forEach(function(i) {
    acc[i] = (acc[i] || 0) + 1;
  });
  return acc;
},{});

看起来更清楚,但在一般情况下使用起来更好:

  if (!acc.hasOwnProperty(i)) acc[i] = 0;
  acc[i]++

对应部分。



products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
    
function countIngredients(p) {
  var counts = p.reduce(function(acc, prod) {
    prod.ingredients.forEach(function(i) {
      acc[i] = (acc[i] || 0) +1;
    })
    return acc;
  },{})
  return counts;
}

document.write(JSON.stringify(countIngredients(products)));




答案 2 :(得分:0)

我会在下划线中这样做

    products = [
           { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
           { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
           { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
           { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
           { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
        ];
    ingredientCount = {};

    _(products).chain()
        .map(function(obj) {return obj.ingredients;}).flatten().each(function(memo, x) {
       ingredientCount[memo] = (ingredientCount[memo] || 0) + 1;
    });

    document.write(JSON.stringify(ingredientCount));

    //this will produce this "{"artichoke":1,"sundried tomatoes":2,"mushrooms":2,"roma":1,"goats cheese":1,"rosemary":1,"black beans":1,"jalapenos":1,"blue cheese":1,"garlic":1,"walnuts":1,"spinach":1,"kalamata olives":1,"sesame seeds":1}"
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>