我如何使用Ramda深度映射对象

时间:2018-11-12 15:41:05

标签: javascript ramda.js

我正在尝试查找所有“模板值”,例如switch (splash) { case one // show splash one case two //show splash two } 使用地图功能来获得以下基本行为:

{ template: 'Date: <now>'}

这是我到目前为止所拥有的。会发生模板对象 的插值,但不会替换该值。

deepMap(mapFn, {a: 1, b: { c: 2, d: { template: 'Date: <now>'}}})

>> {a: 1, b: { c: 2, d: 'Date: 13423234232'}}

2 个答案:

答案 0 :(得分:1)

问题是您再次在映射值上调用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函数是否返回了除原始值以外的其他值,并且在这种情况下不进行递归。

答案 1 :(得分:1)

类似的事情应该起作用:

import * as React from "react"
import Link from "gatsby"
import Markdown from "markdown-to-jsx"

const MagicText = ({ children, linkUrl }) => (
  <Markdown
    options={{
      overrides: {
        replace: Link,
      },
    }}
  >
    {children
      .replace("[replace]", `<replace to=${linkUrl}>`)
      .replace("[/replace]", "</replace>")}
  </Markdown>
)
<MagicText linkUrl="https://www.example.com/">{phrase}</MagicText>

如果要传递转换功能,可以将其稍微更改为

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>'}}})