[英]How can I map over object values using Ramda.js and take only first element?
[英]How can I deeply map over object with Ramda
我正在嘗試使用地圖函數查找所有“模板值”,例如{ template: 'Date: <now>'}
以獲取此基本行為:
deepMap(mapFn, {a: 1, b: { c: 2, d: { template: 'Date: <now>'}}})
>> {a: 1, b: { c: 2, d: 'Date: 13423234232'}}
到目前為止,這就是我所擁有的。 確實發生了模板對象的插值,但不會替換該值。
const obj = {a: 1, b: { c: 2, d: { template: 'Date: <now>'}}};
const deepMap = (fn, xs) =>
mapObjIndexed(
(val, key, obj) =>
or(is(Array, val), is(Object, val))
? deepMap(fn, fn(val))
: fn(val),
xs
);
const checkFn = ({ template }) => template;
const transformFn = (val, key) => {
const interpolated = val.template.replace('<now>', Date.now())
console.log(interpolated);
return interpolated;
};
const mapFn = n =>
checkFn(n)
? transformFn(n)
: n;
console.clear();
deepMap(mapFn, obj);
>> {"a": 1, "b": {"c": 2, "d": {}}}
問題是您再次在映射值上調用deepMap
但是映射值不再是一個對象,而是一個字符串。
or(is(Array, val), is(Object, val))
? deepMap(fn, fn(val))
: fn(val),
在val是{ template: 'Date: <now>'}
,val是一個對象,可以進行深層映射,但是fn(val)
是一個字符串( "Date: 123123123"
),應該簡單地返回它。 一個解決方案是使is
上的映射值,而不是原始值檢查:
(val, key) => {
const mappedVal = fn(val);
return or(is(Array, mappedVal), is(Object, mappedVal))
? deepMap(fn, mappedVal)
: mappedVal;
},
另一種可能性是檢查map函數是否返回了原始值以外的其他值,並且在這種情況下不進行遞歸。
這樣的事情應該起作用:
const {map, has, is} = R const transformTemplate = ({template}) => template.replace('<now>', Date.now()) const deepMap = (xs) => map(x => has('template', x) ? transformTemplate(x) : is(Object, x) || is(Array, x) ? deepMap(x) : x, xs) const result = deepMap({a: 1, b: { c: 2, d: { template: 'Date: <now>'}}}) // => {a: 1, b: {c: 2, d: "Date: 1542046789004"}} console.log(result)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
如果要傳遞轉換函數,可以對其稍作更改以
const deepMap = (transformer, xs) => map(x => has('template', x)
? transformer(x)
: is(Object, x) || is(Array, x)
? deepMap(transformer, x)
: x, xs)
const result = deepMap(transformTemplate, {a: 1, b: { c: 2, d: { template: 'Date: <now>'}}})
當然,您也可以根據需要將其包裝在curry
。
我現在沒有時間研究為什么乍看之下這種方法行不通。 我希望這很簡單:
const deepMap = map(cond([
[has('template'), transformTemplate],
[is(Object), deepMap],
[is(Array), deepMap],
[T, identity]
]))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.