parsing - 在 Ramda 中使用对象创建键值数组
问题描述
我正在使用这样的数据结构
const res = {
"Id": "7ba",
"Group": {
"Id": "ALL",
"Strategy": {
"name": "random",
"Distribution": {
"Origin": 0.5,
"V1": 0.4
}
}
},
"Path": {
"affiliatePage": {
"types": [
{
"Name": "Origin",
"variables": {
"returnUrl": ""
}
},
{
"Name": "V1",
"variables": {
"returnUrl": "asds"
}
}
]
}
}
}
但我希望 Path 对象是这样的
Path : [{key :"affiliatePage" ,
types : [
{
"Name": "Origin",
"variables": {
"returnUrl": ""
}
},
{
"Name": "V1",
"variables": {
"returnUrl": "asds"
}
}
]
}]
和分发对象要像
Distribution : [{key : "Origin" , value: 0.5},{key : "V1" , value: 0.4}]
我尝试了以下事情,但没有帮助,不知道我哪里出错了
const mapper = (val) => { key: val ,
value:GroupData[val]}
const GroupData = R.path(['Group','Strategy','Distribution'])(res)
const PathParser = R.ifElse(
R.isNil(R.prop('Path')),
R.always(null),
R.applySpec({
key: R.keysIn(R.prop('Path'))[0],
types : R.valuesIn(R.prop('Path'))[0].types
})
)
const GroupParser = R.ifElse(
R.isNil(R.prop('Group')),
R.always(null),
R.applySpec({
Distribution : R.map(mapper, R.keysIn(R.path(['Group', 'Strategy', 'Distribution'])))
})
)
const transform = R.applySpec({
Path: PathParser,
Group: GroupParser
})
console.log(transform(res))
我收到错误,因为_arity 的第一个参数必须是不大于十的非负整数。 任何建议,将不胜感激。谢谢!
解决方案
因为您的转换不相关,所以我能看到的最好的事情是将它们编写为单独的函数,一个可以转换一个Distribution
节点,一个可以转换一个Path
节点,然后将它们组合成一个函数,或者通过组合基于镜头的函数或使用 Ramda 的evolve
.
在这两种情况下,各个函数可能如下所示:
const distFn = pipe (toPairs, map (zipObj (['key', 'value'])))
const pathFn = pipe (toPairs, map (([k, v]) => ({key: k, ...v})))
我敢肯定,如果我们尝试,我们可以让后者毫无意义,但我看不出这样做有什么意义。
基于镜头的解决方案可能如下所示:
const transform = pipe (
over (lensPath (['Group', 'Strategy', 'Distribution']), distFn),
over (lensPath (['Path']), pathFn)
)
const distFn = pipe (toPairs, map (zipObj (['key', 'value'])))
const pathFn = pipe (toPairs, map (([k, v]) => ({key: k, ...v})))
const transform = pipe (
over (lensPath (['Group', 'Strategy', 'Distribution']), distFn),
over (lensPath (['Path']), pathFn)
)
const res = {Id: "7ba", Group: {Id: "ALL", Strategy: {name: "random", Distribution: {Origin: 0.5, V1: 0.4}}}, Path: {affiliatePage: {types: [{Name: "Origin", variables: {returnUrl: ""}}, {Name: "V1", variables: {returnUrl: "asds"}}]}}}
console .log(transform (res))
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, toPairs, map, zipObj, over, lensPath} = R </script>
evolve
解决方案可能如下所示:
const transform = evolve ({
Group: {Strategy: {Distribution: distFn}},
Path: pathFn
})
const distFn = pipe (toPairs, map (zipObj (['key', 'value'])))
const pathFn = pipe (toPairs, map (([k, v]) => ({key: k, ...v})))
const transform = evolve ({
Group: {Strategy: {Distribution: distFn}},
Path: pathFn
})
const res = {Id: "7ba", Group: {Id: "ALL", Strategy: {name: "random", Distribution: {Origin: 0.5, V1: 0.4}}}, Path: {affiliatePage: {types: [{Name: "Origin", variables: {returnUrl: ""}}, {Name: "V1", variables: {returnUrl: "asds"}}]}}}
console .log(transform (res))
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {pipe, toPairs, map, zipObj, evolve} = R </script>
在任何一种情况下,如果distFn
并且pathFn
没有在其他地方使用,将它们折叠到 main 函数中并没有什么坏处……除了它可能变得不那么可读并且可能更难以编写测试用例。
两者之间,很难抉择。该lens
解决方案使用更常见的函数式编程习惯用法。但是这个evolve
更明确一些,并且可能性能稍微好一些(未经测试的猜测。)
推荐阅读
- reactjs - 使用 Shopify Collection 在 Gatsby 中以编程方式创建页面
- python - 使用 Kmeans 的错误结果自动编码器(IRV2 功能)
- html - CSS 特异性基于与元素的接近度而不是 CSS 代码中的顺序
- javascript - app.js 在反应中为自定义钩子抛出未定义但为另一个工作
- c# - 激活事件时将数据从 userControl 传递到表单
- postgresql - 在 Oracle 的查询中使用 oracle_fdw 比较操作时 PostgreSQL 太慢
- sql-server - 创建 SSRS 报告,显示每个 RDL 和订阅(如果有多个)的订阅失败历史计数
- encryption - 在 Unqork 中对字符串进行哈希加密
- laravel - 如何将多个域链接到一个 Laravel 项目?
- zsh - zsh 的 tab 补全会覆盖接下来的内容