如何使用无点递归实现使用 Ramda 删除对象中的空值?
How do I implement using point-free recursion to remove null values in objects using Ramda?
我正在学习 pointfree 函数,并尝试以那种方式实现这个递归空值删除器。
有效,但不是点自由:
function removeNulls(obj) {
return R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.filter(R.pipe(R.isNil, R.not)),
R.map(removeNulls)
),
R.identity
)(obj)
}
module.exports = removeNulls
以下是我的无效尝试:
const removeNulls = R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.filter(R.pipe(R.isNil, R.not)),
// throws `ReferenceError: removeNulls is not defined`
R.map(removeNulls)
),
R.identity
)
Javascript 缺乏懒惰在这里是双重杀手:
你不能在它的 const 时调用它,因为你在同一个范围内并且它试图在它的定义中解析 resolveNulls。
此外,您不能只映射(recurseAction(action)),因为定义本身会破坏堆栈,因此您需要将其包装在另一个作用域中才能这样做:
const {ifElse, always, tap, apply, either, is, isNil, not, pipe, filter, map, identity} = require('ramda')
const filterNotNull = filter(pipe(isNil, not))
const log = tap(console.log)
const recurseAction =
action =>
ifElse(
either(is(Array), is(Object)),
pipe(
action,
map(a => recurseAction(action)(a))
),
identity
)
const removeNulls = recurseAction(filterNotNull)
const a = {
a: null,
b: "blah",
c: 2,
d: undefined,
e: {
meow: null,
blah: undefined,
jim: 'bob'
}
}
const b = removeNulls(a)
console.log(b)
幸运的是 JavaScript 有资源来应对它缺乏懒惰的问题。因此,完全可以通过以下方式使用 lambda 函数来声明递归无点解决方案:a => f(a)
。只需将 R.map(removeNull)
替换为 R.map(a => removeNull(a))
.
const removeNulls = R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.filter(R.pipe(R.isNil, R.not)),
R.map(a => removeNulls(a))
),
R.identity
)
对于您的情况,我建议您使用 R.reject
,它与 R.filter
相反。由于您要否定谓词,因此 R.filter(R.pipe(R.isNil, R.not))
等于 R.reject(R.isNil)
const removeNulls = R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.reject(R.isNil),
R.map(a => removeNulls(a))
),
R.identity
)
最后,此函数具有以下结构 ifElse(predicate, whenTrue, identity)
等于 when(predicate, whenTrue)
const removeNulls = R.when(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.reject(R.isNil),
R.map(a => removeNulls(a))
)
)
关于 Declan Whelan 的评论的简化版本,因为数组是对象
const removeNulls = R.when(
R.is(Object),
R.pipe(
R.reject(R.isNil),
R.map(a => removeNulls(a))
)
)
我正在学习 pointfree 函数,并尝试以那种方式实现这个递归空值删除器。
有效,但不是点自由:
function removeNulls(obj) {
return R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.filter(R.pipe(R.isNil, R.not)),
R.map(removeNulls)
),
R.identity
)(obj)
}
module.exports = removeNulls
以下是我的无效尝试:
const removeNulls = R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.filter(R.pipe(R.isNil, R.not)),
// throws `ReferenceError: removeNulls is not defined`
R.map(removeNulls)
),
R.identity
)
Javascript 缺乏懒惰在这里是双重杀手: 你不能在它的 const 时调用它,因为你在同一个范围内并且它试图在它的定义中解析 resolveNulls。
此外,您不能只映射(recurseAction(action)),因为定义本身会破坏堆栈,因此您需要将其包装在另一个作用域中才能这样做:
const {ifElse, always, tap, apply, either, is, isNil, not, pipe, filter, map, identity} = require('ramda')
const filterNotNull = filter(pipe(isNil, not))
const log = tap(console.log)
const recurseAction =
action =>
ifElse(
either(is(Array), is(Object)),
pipe(
action,
map(a => recurseAction(action)(a))
),
identity
)
const removeNulls = recurseAction(filterNotNull)
const a = {
a: null,
b: "blah",
c: 2,
d: undefined,
e: {
meow: null,
blah: undefined,
jim: 'bob'
}
}
const b = removeNulls(a)
console.log(b)
幸运的是 JavaScript 有资源来应对它缺乏懒惰的问题。因此,完全可以通过以下方式使用 lambda 函数来声明递归无点解决方案:a => f(a)
。只需将 R.map(removeNull)
替换为 R.map(a => removeNull(a))
.
const removeNulls = R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.filter(R.pipe(R.isNil, R.not)),
R.map(a => removeNulls(a))
),
R.identity
)
对于您的情况,我建议您使用 R.reject
,它与 R.filter
相反。由于您要否定谓词,因此 R.filter(R.pipe(R.isNil, R.not))
等于 R.reject(R.isNil)
const removeNulls = R.ifElse(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.reject(R.isNil),
R.map(a => removeNulls(a))
),
R.identity
)
最后,此函数具有以下结构 ifElse(predicate, whenTrue, identity)
等于 when(predicate, whenTrue)
const removeNulls = R.when(
R.either(R.is(Array), R.is(Object)),
R.pipe(
R.reject(R.isNil),
R.map(a => removeNulls(a))
)
)
关于 Declan Whelan 的评论的简化版本,因为数组是对象
const removeNulls = R.when(
R.is(Object),
R.pipe(
R.reject(R.isNil),
R.map(a => removeNulls(a))
)
)