【问题标题】:Group and Count Uniquely on Nested Properties with Ramda/LoDash/Underscore使用 Ramda/LoDash/Underscore 对嵌套属性进行唯一分组和计数
【发布时间】:2015-12-18 05:49:38
【问题描述】:

如何对嵌套属性进行分组和计数?抱歉,这似乎是一个非常基本的问题,但老实说,我什至不知道从哪里开始。

编辑我最初对上面的描述过于模糊,可能是因为我的英语不是很好。我将在这里尝试进一步详细说明。

如何按每个产品名称进行分组,然后汇总/计算唯一嵌套项的数量?

我的数据来源:

[
  {
    product_name: 'Cool Gadget',
    offer_code: {name: '50off'}
  },
  {
    product_name: 'Cool Gadget',
    offer_code: {name: '50OFF'}
  },
  {
    product_name: 'Cool Gadget',
    offer_code: {name: '75OFF'}
  },
  {
    product_name: 'Another Cool Gadget'
  },
  {
    product_name: 'Another Cool Gadget',
    offer_code: {name: '50OFF'}
  },
  {
    product_name: 'Another Cool Gadget',
    offer_code: {name: '50OFF'}
  }
]

我的首选输出:

[
  {
    product_name: 'Cool Gadget',
    count: {
      '50OFF': 2,
      '75OFF': 1
    }
  },
  {
    product_name: 'Another Cool Gadget',
    count: {
      '_default': 1,
      '50OFF': 2
    }
  }
]

【问题讨论】:

  • 你想根据什么排序??
  • @RajanSingh 按产品名称排序,然后计算有多少个优惠代码。
  • 我看到从输入到输出的转换没有排序。下面 Scott Christopher 的回答很好,但它只涉及分组,而不涉及排序。我认为这个问题已经结束,因为问题的文本太宽泛了,即使示例输出足够清晰。也许如果将文本编辑得更准确、更精确,它就会重新打开。
  • @ScottSauyet 也许我的英语不是很好。我想“分组依据”或“聚合依据”更有意义。我会进行必要的修改。

标签: javascript underscore.js lodash ramda.js


【解决方案1】:

我们可以使用 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": "酷小工具"}]

我们完成了。

【讨论】:

  • 这太棒了!你应该把它放在博客上作为 Ramda 的入门教程!非常感谢。
猜你喜欢
  • 1970-01-01
  • 2019-06-20
  • 2014-09-22
  • 1970-01-01
  • 2019-07-29
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多