在 Ramda.js 中编写特定对象映射器的更简洁方法
Cleaner way to write a specific object mapper in Ramda.js
我在 Ramda 中编写了一个映射器,它简化了一个对象并删除了具有空数组的属性。这是一件非常简单的事情,但是我必须放在一起的 Ramda 辅助方法会让我在几周后研究这个函数时挠头。
我想知道是否有更简洁的方法来实现相同的结果。
代码如下:
const filters = {
Brand: [],
BusinessUnit: [
{
FilterName: 'BusinessUnit',
KeyItem: 'Beauty'
},
{
FilterName: 'BusinessUnit',
KeyItem: 'Sports'
}
],
Category: [],
SKU: [
{
FilterName: 'SKU',
KeyItem: '9023'
}
]
}
const expectedFilters = {
BusinessUnit: ['Beauty', 'Sports'],
SKU: ['9023']
};
///////////////////////////////////////////////
// is there any way to write it cleaner
const result = R.compose(
R.pickBy(R.pipe(R.isEmpty, R.not)),
R.map(R.map(R.prop('KeyItem')))
)(filters);
///////////////////////////////////////////////
console.log('(expectedFilters:: ', expectedFilters);
console.log('result:: ', result);
console.log('is equal? ', R.equals(expectedFilters, result)); // true
这是 Stackblitz 上此代码 运行 的 link。
我没有发现您的解决方案有任何错误或复杂之处。
我要做的唯一调整是:
- 将
R.pickBy(R.pipe(R.isEmpty, R.not))
替换为 R.pickBy(R.complement(R.isEmpty))
。
- 在映射之前选择。 (目前,您正在映射空数组)
更新
@codepic 指出用 reject
代替组合 filter
和 complement
仍然更好。这是一个明显更好的解决方案:
const transform = pipe (
reject (isEmpty),
map (pluck ('KeyItem') )
)
const filters = {Brand: [], BusinessUnit: [{FilterName: 'BusinessUnit', KeyItem: 'Beauty'}, {FilterName: 'BusinessUnit', KeyItem: 'Sports'}], Category: [], SKU: [{FilterName: 'SKU', KeyItem: '9023'}]}
console .log (
transform (filters)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const {pipe, reject, isEmpty, map, pluck} = R </script>
原始答案
肯定会有一些 clean-up。我认为 complement (isEmpty)
比 pipe (isEmpty, not)
干净得多。 map (prop ('foo') )
有一个 built-in 函数,pluck ('foo')
。虽然 pickBy
可以正常工作,但不久前它变得多余了,因为 filter
将涵盖对象和数组。
所以我的 (现已过时) 版本将如下所示:
const transform = pipe (
filter (complement (isEmpty) )
map (pluck ('KeyItem') )
)
const filters = {Brand: [], BusinessUnit: [{FilterName: 'BusinessUnit', KeyItem: 'Beauty'}, {FilterName: 'BusinessUnit', KeyItem: 'Sports'}], Category: [], SKU: [{FilterName: 'SKU', KeyItem: '9023'}]}
console .log (
transform (filters)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const {pipe, filter, complement, isEmpty, map, pluck} = R </script>
当然,对于将 complement (isEmpty)
提取为 notEmpty
并可能将 filter (notEmpty)
提取为 removeEmpties
之类的东西,存在争议。显然这些很容易做到。
我在 Ramda 中编写了一个映射器,它简化了一个对象并删除了具有空数组的属性。这是一件非常简单的事情,但是我必须放在一起的 Ramda 辅助方法会让我在几周后研究这个函数时挠头。
我想知道是否有更简洁的方法来实现相同的结果。
代码如下:
const filters = {
Brand: [],
BusinessUnit: [
{
FilterName: 'BusinessUnit',
KeyItem: 'Beauty'
},
{
FilterName: 'BusinessUnit',
KeyItem: 'Sports'
}
],
Category: [],
SKU: [
{
FilterName: 'SKU',
KeyItem: '9023'
}
]
}
const expectedFilters = {
BusinessUnit: ['Beauty', 'Sports'],
SKU: ['9023']
};
///////////////////////////////////////////////
// is there any way to write it cleaner
const result = R.compose(
R.pickBy(R.pipe(R.isEmpty, R.not)),
R.map(R.map(R.prop('KeyItem')))
)(filters);
///////////////////////////////////////////////
console.log('(expectedFilters:: ', expectedFilters);
console.log('result:: ', result);
console.log('is equal? ', R.equals(expectedFilters, result)); // true
这是 Stackblitz 上此代码 运行 的 link。
我没有发现您的解决方案有任何错误或复杂之处。
我要做的唯一调整是:
- 将
R.pickBy(R.pipe(R.isEmpty, R.not))
替换为R.pickBy(R.complement(R.isEmpty))
。 - 在映射之前选择。 (目前,您正在映射空数组)
更新
@codepic 指出用 reject
代替组合 filter
和 complement
仍然更好。这是一个明显更好的解决方案:
const transform = pipe (
reject (isEmpty),
map (pluck ('KeyItem') )
)
const filters = {Brand: [], BusinessUnit: [{FilterName: 'BusinessUnit', KeyItem: 'Beauty'}, {FilterName: 'BusinessUnit', KeyItem: 'Sports'}], Category: [], SKU: [{FilterName: 'SKU', KeyItem: '9023'}]}
console .log (
transform (filters)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const {pipe, reject, isEmpty, map, pluck} = R </script>
原始答案
肯定会有一些 clean-up。我认为 complement (isEmpty)
比 pipe (isEmpty, not)
干净得多。 map (prop ('foo') )
有一个 built-in 函数,pluck ('foo')
。虽然 pickBy
可以正常工作,但不久前它变得多余了,因为 filter
将涵盖对象和数组。
所以我的 (现已过时) 版本将如下所示:
const transform = pipe (
filter (complement (isEmpty) )
map (pluck ('KeyItem') )
)
const filters = {Brand: [], BusinessUnit: [{FilterName: 'BusinessUnit', KeyItem: 'Beauty'}, {FilterName: 'BusinessUnit', KeyItem: 'Sports'}], Category: [], SKU: [{FilterName: 'SKU', KeyItem: '9023'}]}
console .log (
transform (filters)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const {pipe, filter, complement, isEmpty, map, pluck} = R </script>
当然,对于将 complement (isEmpty)
提取为 notEmpty
并可能将 filter (notEmpty)
提取为 removeEmpties
之类的东西,存在争议。显然这些很容易做到。