我们可以使用 Ramda 完成一种解决方案。
变量数据 = [
{
product_name: '酷小工具',
报价代码:{名称:'50OFF'}
},
{
product_name: '酷小工具',
报价代码:{名称:'50OFF'}
},
{
product_name: '酷小工具',
报价代码:{名称:'75OFF'}
},
{
product_name: '另一个很酷的小工具'
},
{
product_name: '另一个很酷的小工具',
报价代码:{名称:'50OFF'}
},
{
product_name: '另一个很酷的小工具',
报价代码:{名称:'50OFF'}
}
];
我们将首先创建一个函数,该函数将按产品名称对产品列表进行分组。
常量 groupByProductName = R.groupBy(R.prop('product_name'));
groupByProductName(数据);
// {"Another Cool Gadget": [{"product_name": "Another Cool Gadget"}, {"offer_code": {"name": "50OFF"}, "product_name": "Another Cool Gadget"}, {" offer_code”:{“name”:“50OFF”},“product_name”:“另一个很酷的小工具”}],“很酷的小工具”:[{“offer_code”:{“name”:“50OFF”},“product_name”: “酷小工具”},{“offer_code”:{“name”:“50OFF”},“product_name”:“酷小工具”},{“offer_code”:{“name”:“75OFF”},“product_name”: “酷小工具”}]}
为了帮助计算不同优惠代码的数量,我们将创建一个新函数来按优惠代码名称(如果存在)进行分组,_default
如果不存在则默认为。
我们可以使用这个函数来映射由groupByProductName
.
const groupByOfferCode = R.groupBy(R.pathOr('_default', ['offer_code', 'name']));
R.map(groupByOfferCode, groupByProductName(data));
// {"Another Cool Gadget": {"50OFF": [{"offer_code": {"name": "50OFF"}, "product_name": "Another Cool Gadget"}, {"offer_code": {"name" : "50OFF"}, "product_name": "Another Cool Gadget"}], "_default": [{"product_name": "Another Cool Gadget"}]}, "Cool Gadget": {"50OFF": [{"报价代码”:{“名称”:“50OFF”},“产品名称”:“酷小工具”},{“报价代码”:{“名称”:“50OFF”},“产品名称”:“酷小工具”}],“ 75OFF": [{"offer_code": {"name": "75OFF"}, "product_name": "酷小工具"}]}}
一旦我们按名称对报价代码进行分组,我们将创建一个新函数来用每个数组的长度交换代码数组。
常量 countOfferCodes = R.map(R.length);
R.map(countOfferCodes, R.map(groupByOfferCode, groupByProductName(data)));
// {"Another Cool Gadget": {"50OFF": 2, "_default": 1}, "Cool Gadget": {"50OFF": 2, "75OFF": 1}}
一旦我们定义了这些函数,我们就可以得到接近你想要的输出的东西。
常量过程 = 产品 => R.map(countOfferCodes, R.map(groupByOfferCode, groupByProductName(products)));
处理数据);
// {"Another Cool Gadget": {"50OFF": 2, "_default": 1}, "Cool Gadget": {"50OFF": 2, "75OFF": 1}}
鉴于所有这些函数都将它们的输出直接提供给下一个的输入,因此可以将其声明R.pipe
为用于创建转换管道。
常量进程 = R.pipe(
groupByProductName,
R.map(groupByOfferCode),
R.map(countOfferCodes)
);
您可能已经注意到,我们R.map
在管道中有两个相邻的函数。由于法律规定R.pipe(R.map(f), R.map(g))
必须相同,因为R.map(R.pipe(f, g))
我们可以通过将管道修改为以下内容来防止循环遍历列表两次。
常量进程 = R.pipe(
groupByProductName,
R.map(R.pipe(
groupByOfferCode,
countOfferCodes
))
);
现在要将输出转换为所需的形状,我们可以创建一个将对象转换为列表的函数,我们可以将其添加到管道的末尾。
const objToList = R.pipe(
R.toPairs,
R.map(R.zipObj(['product_name', 'count']))
);
最后,我们可以在管道中添加一个函数来按产品名称排序。所以大家一起:
常量 groupByProductName = R.groupBy(R.prop('product_name'));
const groupByOfferCode = R.groupBy(R.pathOr('_default', ['offer_code', 'name']));
常量 countOfferCodes = R.map(R.length);
const objToList = R.pipe(
R.toPairs,
R.map(R.zipObj(['product_name', 'count']))
);
常量进程 = R.pipe(
groupByProductName,
R.map(R.pipe(
groupByOfferCode,
countOfferCodes
)),
对象列表,
R.sortBy(R.prop('product_name'))
);
处理数据);
// [{"count": {"50OFF": 2, "_default": 1}, "product_name": "Another Cool Gadget"}, {"count": {"50OFF": 2, "75OFF": 1 }, "product_name": "酷小工具"}]
我们完成了。