【问题标题】:Group many arrays into one based on object properties根据对象属性将多个数组组合为一个
【发布时间】:2019-09-09 00:17:51
【问题描述】:

我正在开发一个电子商务网站。我必须管理产品变化。 REST API 响应如下所示:

"variations": [
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "L"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "XXL"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "Azul"
      },
      {
        "name": "Talle",
        "valueName": "M"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "S"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "XL"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "Azul"
      },
      {
        "name": "Talle",
        "valueName": "S"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "M"
      }
    ]
  }
]

这个 JSON 对我来说在前端工作效率很低。很难根据其类型(名称)和值(值名称)对变体进行分组,因为它们位于不同的“数组数组”上。

最终的结果应该是这样的:

variations: [
  {
    name: 'Color',
    values: ['Gris', 'Azul']
  },
  {
    name: 'Talle',
    values: ['S', 'M', 'L', 'XL', 'XXL']
  }
]

到目前为止,我已经达到了这个结果:

[
  { name: "Color", values: ["GRIS"] },
  { name: "Talle", values: ["L"] },
  { name: "Color", values: ["GRIS"] },
  { name: "Talle", values: ["XXL"] },
  { name: "Color", values: ["Azul"] },
  { name: "Talle", values: ["M"] },
  { name: "Color", values: ["GRIS"] },
  { name: "Talle", values: ["S"] },
  { name: "Color", values: ["GRIS"] },
  { name: "Talle", values: ["XL"] },
  { name: "Color", values: ["Azul"] },
  { name: "Talle", values: ["S"] },
  { name: "Color", values: ["GRIS"] },
  { name: "Talle", values: ["M"] }
]

基于此代码:

let variations = this.$page.product.variations;
let newArr = [];

variations.forEach(variation => {
        newArr.push(
          Object.values(
            variation.attributeCombinations.reduce(
              (result, { name, valueName }) => {
                // Create new group
                if (!result[name]) {
                  result[name] = {
                    name,
                    values: []
                  };
                }
                // Append to group
                result[name].values.push(valueName);

                return result;
              },
              {}
            )
          )
        );
      });
return newArr.reduce((acc, cur) => acc.concat(cur));

【问题讨论】:

  • 您想要的输出与原始结构相比丢失了信息。例如,原始结构没有 Azul-XL 组合。此信息无法从您想要的输出中得出。你确定吗?
  • @trincot 是的!我注意到了这一点。但是,就目前而言,以及我将为此功能提供的特定用例,这并不是真正的问题。不过谢谢!
  • 那么任何答案都符合您的需求吗?还是您还在寻找答案?
  • Naga 的回答正是我所需要的。非常感谢

标签: javascript arrays object ecmascript-2016


【解决方案1】:

为了达到预期的效果,请使用以下使用 reduce , forEach 和每个循环的索引的选项

  1. 循环遍历变量数组
  2. 对于位置 0 的第一个索引,推送到累加器 (acc)
  3. 使用第二个循环,使用 .forEach 循环遍历属性组合
  4. 将 valueNames 推送到相应的名称 - Color 和 Talle

var arr = {"variations": [
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "L"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "XXL"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "Azul"
      },
      {
        "name": "Talle",
        "valueName": "M"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "S"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "XL"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "Azul"
      },
      {
        "name": "Talle",
        "valueName": "S"
      }
    ]
  },
  {
    "attributeCombinations": [
      {
        "name": "Color",
        "valueName": "GRIS"
      },
      {
        "name": "Talle",
        "valueName": "M"
      }
    ]
  }
]
          }


console.log(arr.variations.reduce((acc, val, idx) => {
  val.attributeCombinations.forEach((v, i) => {
  if(idx === 0) {
    acc.push({name: v.name , valueName:  Array.of(v.valueName)})
  }else{
    i === 0 ? acc[0].valueName.push(v.valueName) : acc[1].valueName.push(v.valueName) 
  }
})
  return acc
},[]).map(v => v = {name :v.name,  valueName: [...new Set(v.valueName)]}));

codepen - https://codepen.io/nagasai/pen/ZZxVzp?editors=1010

【讨论】:

    【解决方案2】:

    您可以使用函数reduce 进行分组,使用函数Object.values 提取值。

    Set 对象提供了一种删除重复值的方法。

    let variations = [   {     "attributeCombinations": [       {         "name": "Color",         "valueName": "GRIS"       },       {         "name": "Talle",         "valueName": "L"       }     ]   },   {     "attributeCombinations": [       {         "name": "Color",         "valueName": "GRIS"       },       {         "name": "Talle",         "valueName": "XXL"       }     ]   },   {     "attributeCombinations": [       {         "name": "Color",         "valueName": "Azul"       },       {         "name": "Talle",         "valueName": "M"       }     ]   },   {     "attributeCombinations": [       {         "name": "Color",         "valueName": "GRIS"       },       {         "name": "Talle",         "valueName": "S"       }     ]   },   {     "attributeCombinations": [       {         "name": "Color",         "valueName": "GRIS"       },       {         "name": "Talle",         "valueName": "XL"       }     ]   },   {     "attributeCombinations": [       {         "name": "Color",         "valueName": "Azul"       },       {         "name": "Talle",         "valueName": "S"       }     ]   },   {     "attributeCombinations": [       {         "name": "Color",         "valueName": "GRIS"       },       {         "name": "Talle",         "valueName": "M"       }     ]   } ];
    let result = Object.values(variations.reduce((a, {attributeCombinations: combinations}) => {
      combinations.forEach(({name, valueName}) => {
        (a[name] || (a[name] = {name, values: new Set()})).values.add(valueName);
      });
      
      return a;
    }, {}));
    
    console.log(Array.from(result[0].values));// for understanding the object set
    console.log(result);
    .as-console-wrapper { min-height: 100%; }

    【讨论】:

    • 我不知道 Set 对象。你的代码真的很干净!结果并不完全符合我的需要,但非常感谢您的帮助。谢谢!
    【解决方案3】:

    您可以使用reduce 循环遍历数组并汇总为一个对象。使用forEach 循环通过attributeCombinations 并构造所需的输出。使用Object.values将对象转化为数组。

    var variations = [{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"L"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"XXL"}]},{"attributeCombinations":[{"name":"Color","valueName":"Azul"},{"name":"Talle","valueName":"M"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"S"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"XL"}]},{"attributeCombinations":[{"name":"Color","valueName":"Azul"},{"name":"Talle","valueName":"S"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"M"}]}];
    
    var result = Object.values(variations.reduce((c, v) => {
      v.attributeCombinations.forEach(({name,valueName}) => {
        c[name] = c[name] || {name,values: []}
        c[name].values.push(valueName);
      });
      return c;
    }, {}));
    
    console.log(result);

    如果您想要唯一值,可以使用Set 并添加另一个循环将Set 对象转换为数组。

    var variations = [{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"L"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"XXL"}]},{"attributeCombinations":[{"name":"Color","valueName":"Azul"},{"name":"Talle","valueName":"M"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"S"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"XL"}]},{"attributeCombinations":[{"name":"Color","valueName":"Azul"},{"name":"Talle","valueName":"S"}]},{"attributeCombinations":[{"name":"Color","valueName":"GRIS"},{"name":"Talle","valueName":"M"}]}]
    
    var result = Object.values(variations.reduce((c, v) => {
      v.attributeCombinations.forEach(({name,valueName}) => {
        c[name] = c[name] || {name,values: new Set}
        c[name].values.add(valueName);
      });
      return c;
    }, {})).map(o => {
      o.values = [...o.values.values()]
      return o;
    });
    
    console.log(result);

    【讨论】:

      猜你喜欢
      • 2021-04-21
      • 2019-05-05
      • 2016-04-20
      • 1970-01-01
      • 2012-02-24
      • 1970-01-01
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多