javascript - JavaScript - How to merge a complex nested object using another as reference to iterate?
问题描述
I have an object with multiple keys in the shape of:
{
'.[key1].[key2].[key3]': {},
'.[key1].[key2].[key3].[key4]': {},
'.[key1].[key2].[key3].[key5]': {},
}
Given this example is pretty obvious that I generated this code using some reference in order to create these keys.
Below is the reference object
const invoiceShape = {
'cfdi\\:CdfiRelacionados': {
'tfd\\:CfdiRelacionado': {},
},
'cfdi\\:Emisor': {},
'cfdi\\:Receptor': {},
'cfdi\\:Conceptos': {
'cfdi\\:Concepto': {
'cfdi\\:Impuestos': {
'cfdi\\:Traslados': {
'cfdi\\:Traslado': {},
},
'cfdi\\:Retenciones': {
'cfdi\\:Retencion': {},
},
'cfdi\\:InformacionAduanera': {},
'cfdi\\:CuentaPredial': {},
'cfdi\\:Parte': {
'cfdi\\:InformacionAduanera': {},
},
},
},
},
'cfdi\\:Complemento': {
'tfd\\:TimbreFiscalDigital': {},
},
'cfdi\\:Addenda': {},
};
So, my object looks like this
const invoiceParsed = {
'.cfdi\\:Conceptos.cfdi\\:Concepto.cfdi\\:Impuestos': {},
'.cfdi\\:Conceptos.cfdi\\:Concepto.cfdi\\:Impuestos.cfdi\\:Traslados': {},
'.cfdi\\:Conceptos.cfdi\\:Concepto.cfdi\\:Impuestos.cfdi\\:Retenciones': {},
}
The invoiceShape object has empty values on the keys, but now that the invoiceParsed object is filled I want it to fill the invoiceShape as well, I figured out that parsing every nested level spliting the "." in the keys of invoiceParsed is a more effective way to iterate over the reference object, but if I iterate over the 'cfdi\\:Conceptos'
key a second time I just overwrite the key value, instead of merging it
I'm not posting any code on the iteration, because I want read your ideas, algorithms or packages you would use as lodash for example
解决方案
尽管partial.lenses是处理深度嵌套数据的另一个出色工具,但我喜欢Ramda的类似功能。
这里有两个可行的解决方案。第一个使用 Ramda 的几个函数。第二个主要是 vanilla JS,只有 Ramda 的两个功能:
const shape = {
a: {
b: {
c: {}
}
},
d: {
e: {
f: {
g: {}
}
}
},
h: {}
}
const parsed = {
'a': { v: 1 },
'a.b': { v: 2 },
'a.b.c': { v: 3 },
'd': { v: 4 },
'd.e': { v: 5 },
'd.e.f': { v: 6 },
'd.e.f.g': { v: 7 },
'h': { v: 8 }
}
const fillShapeWithParsed = s =>
R.pipe(
R.toPairs,
R.reduce(
(acc, [k, v]) =>
R.over(R.lensPath(k.split('.')), R.merge(v), acc),
s
)
)
console.log(
fillShapeWithParsed(shape)(parsed)
)
const merge = x => y => ({ ...y, ...x })
const fillShapeWithParsedVanilla = s => p =>
Object.entries(p).reduce(
(acc, [k, v]) =>
R.over(R.lensPath(k.split('.')), merge(v), acc),
s
)
console.log(
fillShapeWithParsedVanilla(shape)(parsed)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
对于同时使用 Ramda 和 partial.lenses 的混合解决方案,只需换掉示例中R.over(
以此开头的行:
L.modify(k.split('.'), R.merge(v), acc)
推荐阅读
- swift - SwiftUI 预览失败并出现 __designTimeString 错误
- html - 引导模式无法正确传递数据
- image - 如何在flutter web中将网络图像显示为NetworkImage之前调整其大小?
- typescript - React admin ReferenceInput 组件在 hydra 响应中无法按预期工作
- python - SMT求解器中的数据类型,支持正常的加法、异或或同时运算
- php - 由于 PHP 版本,Apache 中的 PHPMyAdmin 500 内部服务器错误
- javascript - 使用 discord.js 从文本通道获取最后一条消息
- python - $gme 或 gme 的正则表达式,在 python 中之前或之后有空格或没有空格
- javascript - 计算 json 数组对象并使用 SUM 结果创建一个新数组
- javascript - 打字机使 div 在更小的设备上移动