如何将arr数组转会为newArr数组
// 转换成多维数组
function getMultidimensional(arr) {
const data = {};
arr.forEach((item) => {
const list = data[item.name] || [];
list.push(item);
data[item.name] = list;
});
return Object.keys(data).map((key) => data[key]);
}
// 求笛卡尔积
function getCartesianProduct(array) {
if (!Array.isArray(array)) return [[]]; // 判断数组
array = array.filter((_) => _.length > 0); // 清除数组里面的空数组
if (array.length < 2) return array; // 数组少于两个 GG
const list1 = array.splice(0, 1)[0]; // 取出第一个
const list2 = array.splice(0, 1)[0]; // 取出第二个
const list = [];
list1.forEach((_list1) => {
list2.forEach((_list2) => {
if (_list1.name) {
list.push({
[_list1.name]: _list1.value,
[_list2.name]: _list2.value,
});
} else {
list.push({
..._list1,
[_list2.name]: _list2.value,
});
}
});
});
return getCartesianProduct([list].concat(array));
}
const arr = [
{ name: "color", value: "白色" },
{ name: "color", value: "黑色" },
{ name: "size", value: "x" },
{ name: "size", value: "M" },
];
const list = getCartesianProduct(getMultidimensional(arr));
console.log(list);
先给试验数据(@唐云 下次记得贴代码出来)
const arr = [
{
"productAttributeld": 2,
"value": "白色",
"name": "color"
},
{
"productAttributeld": 2,
"value": "黑色",
"name": "color"
},
{
"productAttributeld": 5,
"value": "M",
"name": "size"
},
{
"productAttributeld": 5,
"value": "X",
"name": "size"
}
];
然后(借助了 lodash 的 groupBy,因为懒得自己写)
import _ from "lodash";
// 先按 productAttributeld 分组,将分组结构转成数组(数组的数组)
const attributes = _(arr).groupBy(it => it.productAttributeld)
.mapValues(list => list.map(({ name, value }) => ({ [name]: value })))
.values()
.value();
console.log(attributes);
// [
// [ { color: '白色' }, { color: '黑色' } ],
// [ { size: 'M' }, { size: 'X' } ]
// ]
// 笛卡尔积
// 以 [{}] 作为初始值,可以理解为数学算累积乘积的初始值 1
// 遍历上述属性组列表,用上次的乘积结果(第 1 次是初始值)中的每一个元素,与新的属性组相乘,
// 再展开成一维数组
const result = attributes.reduce(
(r, attributeValues) => r.flatMap(it => attributeValues.map(attr => ({ ...it, ...attr }))),
[{}]);
console.log(result);
示意图:
function getGroupResult(dataList) {
return dataList.reduce((r, { name, value }) => {
r[name] = r[name] || [];
r[name].push(value);
return r;
}, {})
}
function combination(groupInfo) {
return Object.entries(groupInfo).reduce((result, [key, valueList]) => {
return valueList.reduce((subResult, value) => {
const tail = result.map(i => ({ ...i, [key]: value }));
return subResult.concat(tail)
}, [])
}, [{}])
}
调用:
const groupResult = getGroupResult(data);
const result = combination(groupResult);
console.log(result);
5 回答9.4k 阅读✓ 已解决
9 回答2.5k 阅读✓ 已解决
14 回答3.5k 阅读
4 回答1.4k 阅读✓ 已解决
6 回答1.2k 阅读✓ 已解决
6 回答1.8k 阅读✓ 已解决
12 回答5.5k 阅读
我还是强烈推荐写前端的朋友可以多用用
reduce
,真的是太好用了,完整代码如下,提供了任意多个属性都被支持的能力,但是没有对值进行去重,这个应该是在组装arr
时就进行的处理:这个应该是一个可以自定义数据字段的商城类的系统里面的,数组中每一项都是某一个类型定义的属性,处理逻辑基本上就是两步:
得到的结果为:
然后开始组合:
得到如下结果:
使用下面这样的更多属性测试:
得到如下结果:
最后封装一个函数: