Если вы используете (или хотите использовать) Рамда (отказ от ответственности: я один из его основных авторов), это может сработать для вас. У Рамды нет функции deepMap
, но ее легко написать. И используя это, ваша функция преобразования является однострочной:
const deepMap = (fn) => (obj) =>
is (Object, obj) ? map (deepMap (fn)) (obj) : fn (obj)
const transform = compose(applySpec, deepMap (compose (path, split('.'))))
const objToTransform = {a: "aValue", b: {c: "cValue", d: "dValue"}}
const filteringObj = {field1: "a", field2: {subfield1: "b.c", subfield2: "b.d"}}
console .log (transform (filteringObj) (objToTransform))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {is, map, compose, applySpec, path, split } = R </script>
Ключевым моментом здесь является applySpec
, который можно использовать напрямую с немного другим форматом filteringObj
. Это даст желаемые результаты:
applySpec ({
field1: path (["a"]),
field2: {
subfield1: path (["b", "c"]),
subfield2: path (["b", "d"])
}
}) (objToTransform)
Остальная часть функции transform
состоит в простом преобразовании filteringObj
в форму выше.
Если вы хотите продолжать вызывать ее как задано в вопросе, это как transform (objToTransform, filteringObj)
, а не trasform (filteringObj) (objToTransform)
, только немного сложнее:
const transform = (objToTransform, filteringObj) =>
applySpec(deepMap (compose (path, split('.'))) (filteringObj)) (objToTransform)
Вы можете написать свои собственные версии этих функций Ramda, это в основном легко . Но версия applySpec
, которая работает с вложенными свойствами, будет немного сложнее.