合并对象字段以使用 Ramda 创建新字段

Merge fields of object to create new field with Ramda

我有一个集合,我想从中获取一些值,并将它们合并在一起形成一个新值。到目前为止,我已经看过 R.evolve,但没有运气(因为 medias 也是一个集合。

这就是我的开头:

[{
  "permalink": "http://example.com/1",
  "medias": [{
    "filename": "image_1.png",
  }]
}, {
  "permalink": "http://example.com/3",
  "medias": [{
    "filename": "image_3.png",
  }]
}]

这就是我想结束的:

[{
  "permalink": "http://example.com/1",
  "medias": [{
    "filename": "image_1.png",
    "image_url": "http://example.com/1/image_1.png"
  }]
}, {
  "permalink": "http://example.com/3",
  "medias": [{
    "filename": "image_3.png",
    "image_url": "http://example.com/3/image_3.png"
  }]
}]

本质上,我们正在做的是在每个 filename 前面加上一个 permalink

这是我迄今为止一直在做的事情,不幸的是,当 运行 在 medias 上进行转换时,我无法访问 permalink 属性.

const mapMedia = R.map(
  // can’t get access to the `permalink` in here?
)

const transformations = {
  medias: mapMedia
}

const transform = R.compose(
  R.map(R.evolve(transformations)),
)(data)

所以问题是您需要的数据不在范围内。在我看来,解决这个问题的最简单方法是添加一些范围!

首先,您不需要 compose 调用,因为您只提供了一个功能。所以我们可以替换

const transform = R.compose(
  R.map(R.evolve(transformations)),
)(data)

只有

const transform = R.map(R.evolve(transformations)),

(我还删除了使用 (data) 的调用,因为我试图将其构建为可重用函数。稍后我们将使用 transform(data) 调用它。

现在我们必须添加上下文,以便 transformations 将对象包含在范围内。我们可以这样做:

const transform = R.map(image => R.evolve(transformations(image), image));

当然,这意味着 transformations 需要更改以考虑到这一点。我们可以这样做:

const transformations = image => ({
  medias: mapMedia(image.permalink)
})

... 而这又需要更改为 mapMedia。我认为它应该只需要知道永久链接而不是整个图像,所以我们可以像上面那样只传递它。 mapMedia 现在看起来像这样:

const mapMedia = permalink => R.map(
  medium => // do something with `medium` and `permalink`
);

您可以通过多种方式完成这最后一步。其中之一,与您对 evolve 的使用相当一致:

const mapMedia = permalink => R.map(
  medium => assoc('image_url', permalink + '/' + medium.filename, medium)
);

evolveassoc is to investigate the various lens-related functions in Ramda, such as lensProp, over, and set 的另一种选择。

现在,如果这些辅助函数仅用于此目的,您可能不希望它们把事情弄得一团糟,您可以选择将它们内联到您的主函数中。如果你喜欢,你可以将以上所有内容组合成

const addUrls = map(
  image => evolve({
    medias: map(medium => assoc('image_url', image.permalink + '/' + medium.filename, medium)),
  }, image)
);

可以看到separate functions approach or the combined one in the Ramda REPL. For good measure, there's also a version using lenses.


(另外,单词 "media" 已经是复数。单数是 "medium"。"medias" 没有充分的理由。)