【问题标题】:Chaining array methods (filter, map, reduce) instead of using double loop链接数组方法(filter、map、reduce)而不是使用双循环
【发布时间】:2020-11-25 06:34:23
【问题描述】:

我遇到了一个我无法解决的问题...... 所以这就是我想要做的。

给定以下对象数组,

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

我知道我可以通过嵌套循环运行它以按成分名称添加键,然后在循环计数时递增值,如下所示:

      let ingredientCount = {}; 

  for (i = 0; i < products.length; i += 1) {
    for (j = 0; j < products[i].ingredients.length; j += 1) { //loop ingredients 
      ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1; 
    }
  }

因此,componentCount 应该类似于:{ "artichoke": 1 "mushrooms": 2 } ***

这里的问题是我需要使用 map 和 reduce 来创建与上面相同的结果。

let ingredientCount = {}

    ingredientCount = 
    products.filter ((value) => {
        // filter out arrays within ingredients 
        // so out come should be like  
        /* 
        [ingredients: ['artichoke', 'sundried tomatoes', 'mushrooms']
        ,ingredients: ['roma', 'sundried tomatoes', 'goats cheese', 'rosemary']
        ,ingredients: ['black beans', 'jalapenos', 'mushrooms']
        ,ingredients: ['blue cheese', 'garlic', 'walnuts']
        ,ingredients: ['spinach', 'kalamata olives', 'sesame seeds']
        */

    }).map ((value) => {
        /* then take out ingredients and map this array to  
        arthichoke: ['artichoke','artichoke','artichoke']
        sundried tomatoes: ['sundried tomatoes']
        etc... 
        */

    
    }).reduce((acc, value) => {
        /* then reduce arrays within each key to numbers. 
        hence, the output should be 

        artichokes: artichokes.length (i.e. 3 )
        sundried toamatoes: 1
        
        */
    })

无论如何我可以使用上述数组方法获得完全相同的结果而不必使用循环吗?

提前致谢。

【问题讨论】:

  • 我认为循环很好。但是您只想使用数组方法。请你解释一下过滤器部分,因为我不明白
  • 我不认为这种连接能更好地解决问题,因为两个主要原因,第一它混淆了代码,第二性能最差。另一方面,循环示例更具可读性和更快

标签: javascript arrays dictionary reduce


【解决方案1】:

您需要使用map()flat(),然后是reduce()。函数flat() 将数组展平。

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

let obj = products
              .map(p => p.ingredients)
              .flat()
              .reduce((obj, val) => {
                  obj[val] = (obj[val] || 0) + 1;
                  return obj;
              }, {});
console.log(obj);

【讨论】:

    【解决方案2】:

    您可以使用两个forEachmap,并维护一个只需要更新的最终数组。

    let 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 },
    ];
    
    let iCount = {};
    products.forEach((c) => c.ingredients.forEach((i) => iCount.hasOwnProperty(i) ? iCount[i]++ : iCount[i] = 1));
    console.log(iCount);

    【讨论】:

    • 你使用的是map(),就像forEach()一样。
    【解决方案3】:

    使用数组的 .reduce 方法和 .forEach 方法的解决方案。

    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 },
    ];
    
    var result = products.reduce((acc,obj) => 
       {obj.ingredients.forEach(ob=> acc[ob] = acc[ob]+1 || 1)
        return acc;
    },{});
    
    console.log(result);

    【讨论】:

      【解决方案4】:

      使用Array.prototype.reduce 来减少数组并随时增加计数。

      const 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
        },
      ];
      
      const result = products.reduce((acc, { ingredients }) => {
        ingredients.forEach((ingredient) => {
          acc[ingredient] = (acc[ingredient] || 0) + 1;
        });
        return acc;
      }, Object.create(null));
      
      console.log(result);

      【讨论】:

        【解决方案5】:

        使用flatMapreduce。 (除了??, 运算符)

        const 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 },
        ];
        
        const ingredientCount = products
          .flatMap(({ ingredients }) => ingredients)
          .reduce((acc, item) => ((acc[item] = (acc[item] ?? 0) + 1), acc), {});
        
        console.log(ingredientCount);

        【讨论】:

          猜你喜欢
          • 2017-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-23
          • 2021-06-06
          • 2019-11-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多