从多维数组javascript中提取特定值

时间:2015-03-28 02:00:47

标签: javascript multidimensional-array higher-order-functions

我有一个多维数组,如下所示。我希望从中提取所有ingredients值,然后对它们执行操作,例如计算每个值的数量。

var 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 }
];

我使用Underscore.js,_.flatten()和vanilla javascript函数map()中的函数完成了此操作,但我必须使用map()两次。一旦提取所有成分,然后制作哈希样式结构,计算每个成分发生的次数。我将这些计数存储在一个单独的对象中,在这种情况下为ingredientCount

var ingredientCount = {};
_.flatten(products.map(function(x) {
    return x.ingredients;
})).map(function(y){
    return ingredientCount[y] = (ingredientCount[y] || 0) + 1;
});

console.log(ingredientCount);将输出以下列表:

{ 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 }

我已经解决了我的问题,但我觉得应该有一种更干净,更有效的方法来做到这一点,而不使用map()两次。谁能帮我吗?如果这是一个重复的问题,我会提前道歉。

2 个答案:

答案 0 :(得分:1)

这是我在普通JavaScript中可以想到的最优雅的方式,因为它没有使用任何中间数据结构(原始解决方案创建了两个数组,然后将它们组合到最终对象中)。

var counts = products.reduce(function (result, product) {
    product.ingredients.forEach(function (ingredient) {
        result[ingredient] = (result[ingredient] || 0) + 1;
    });
    return result;
}, {});

答案 1 :(得分:0)

你可以使用递归:

var 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 }
];    

// written by hand, with <3
function ic(p,o,i,b,g) {
  i|=0;g|=0;
  if(!b&&p&&!p.ingredients)
    while((g=ic(p[g].ingredients,o,0,g+1))&&p[g]);
  else {
    o[p[i]]=(o[p[i]]|0)+1;
    return p[i+1]?ic(p,o,i+1,b):b;
  }
}
    
var ingredientCount = {};
ic(products, ingredientCount);

document.body.innerHTML = JSON.stringify(ingredientCount).replace(/(\,)/g,"$1<br/>");
body {font-family: monospace }
<body></body>

编辑:不,我不认真。 But its almost 3x faster