使用 Ramda 根据条件过滤对象
Filtering objects based on conditions using Ramda
我想使用 Ramda 过滤掉以下数据。期望的结果是显示属性 usage === 'Defining'
.
const data =
[{
"attributes":
[
{"usage": "Descriptive"},
{"usage": "Defining"}
]
}]
到目前为止,这就是我所做的,它没有过滤掉数据并返回整个对象。
R.filter(
R.compose(
R.any(R.propEq('usage', 'Defining')),
R.prop('attributes')
)
)(data)
以下是我想要达到的预期结果:
[{
"attributes":
[
{"usage": "Defining"}
]
}]
您正在尝试在此处同时执行地图和过滤器,因此值得为每个单独的函数,然后将它们组合在一起以获得您想要的:
const data =
[{
"attributes":
[
{"usage": "Descriptive"},
{"usage": "Defining"}
]
},
{
"attributes":
[
{"usage": "Descriptive"},
{"usage": "Definingx"}
]
}]
const removeObjectsWithoutDefining = filter(
compose(any(equals('Defining')), map(prop('usage')), prop('attributes'))
);
const adjustProp = curry((f, k, o) => ({
...o,
[k]: f(o[k]),
}));
const mapAttributesToRemoveNonDefining = map(
adjustProp(
filter(propEq('usage', 'Defining')),
'attributes',
),
)
const f = compose(mapAttributesToRemoveNonDefining, removeObjectsWithoutDefining);
f(data);
如果我理解正确你想要做什么,那么 where
在你想要基于属性进行过滤时非常有用。但是您想将它与 map
结合起来。虽然 Ramda 不提供 filterMap
,但编写我们自己的非常容易。我们创建一个接受过滤函数和映射函数的函数,以及 returns 一个接受数组并仅映射通过过滤器的结果的函数。以这种方式分解问题,我们可以这样写:
const filterMap = (f, m) => (xs) =>
chain ((x) => f (x) ? [m (x)] : [], xs)
const definingProps = filterMap (
where ({attributes: any (propEq ('usage', 'Defining'))}),
over (lensProp('attributes'), filter (propEq ('usage', 'Defining')))
)
const data = [
{id: 1, attributes: [{usage: "Descriptive"}, {usage: "Defining"}]},
{id: 2, attributes: [{usage: "Descriptive"}, {usage: "Something Else"}]},
{id: 3, attributes: [{usage: "Defining"}, {usage: "Filtering"}]}
]
console .log (definingProps (data))
.as-console-wrapper {min-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {curry, chain, where, any, propEq, over, lensProp, filter} = R </script>
显然,将 propEq ('usage', 'Defining')
提取到独立函数中是有道理的;留作 reader.
的练习
我想使用 Ramda 过滤掉以下数据。期望的结果是显示属性 usage === 'Defining'
.
const data =
[{
"attributes":
[
{"usage": "Descriptive"},
{"usage": "Defining"}
]
}]
到目前为止,这就是我所做的,它没有过滤掉数据并返回整个对象。
R.filter(
R.compose(
R.any(R.propEq('usage', 'Defining')),
R.prop('attributes')
)
)(data)
以下是我想要达到的预期结果:
[{
"attributes":
[
{"usage": "Defining"}
]
}]
您正在尝试在此处同时执行地图和过滤器,因此值得为每个单独的函数,然后将它们组合在一起以获得您想要的:
const data =
[{
"attributes":
[
{"usage": "Descriptive"},
{"usage": "Defining"}
]
},
{
"attributes":
[
{"usage": "Descriptive"},
{"usage": "Definingx"}
]
}]
const removeObjectsWithoutDefining = filter(
compose(any(equals('Defining')), map(prop('usage')), prop('attributes'))
);
const adjustProp = curry((f, k, o) => ({
...o,
[k]: f(o[k]),
}));
const mapAttributesToRemoveNonDefining = map(
adjustProp(
filter(propEq('usage', 'Defining')),
'attributes',
),
)
const f = compose(mapAttributesToRemoveNonDefining, removeObjectsWithoutDefining);
f(data);
如果我理解正确你想要做什么,那么 where
在你想要基于属性进行过滤时非常有用。但是您想将它与 map
结合起来。虽然 Ramda 不提供 filterMap
,但编写我们自己的非常容易。我们创建一个接受过滤函数和映射函数的函数,以及 returns 一个接受数组并仅映射通过过滤器的结果的函数。以这种方式分解问题,我们可以这样写:
const filterMap = (f, m) => (xs) =>
chain ((x) => f (x) ? [m (x)] : [], xs)
const definingProps = filterMap (
where ({attributes: any (propEq ('usage', 'Defining'))}),
over (lensProp('attributes'), filter (propEq ('usage', 'Defining')))
)
const data = [
{id: 1, attributes: [{usage: "Descriptive"}, {usage: "Defining"}]},
{id: 2, attributes: [{usage: "Descriptive"}, {usage: "Something Else"}]},
{id: 3, attributes: [{usage: "Defining"}, {usage: "Filtering"}]}
]
console .log (definingProps (data))
.as-console-wrapper {min-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {curry, chain, where, any, propEq, over, lensProp, filter} = R </script>
显然,将 propEq ('usage', 'Defining')
提取到独立函数中是有道理的;留作 reader.