javascript – Ramda js:具有嵌套数组对象的深层嵌套对象的镜头

使用Ramda.js(和镜头),我想修改下面的JavaScript对象,为ID =“/ 1 / B / i”的对象更改“NAME:VERSION1”到“NAME:VERSION2”.

我想使用镜头,因为我只想改变一个深层嵌套的值,但是保留整个结构不变.

我不想使用lensIndex,因为我不知道数组将会有什么顺序,所以我想通过查找其“id”字段来“查找”数组中的对象.

我可以用镜头做这个,还是应该用不同的方式做?

{
  "id": "/1",
  "groups": [
    {
      "id": "/1/A",
      "apps": [
        {
          "id": "/1/A/i",
          "more nested data skipped to simplify the example": {} 
        }
      ]
    },
    {
      "id": "/1/B",
      "apps": [
        { "id": "/1/B/n", "container": {} },
        {
          "id": "/1/B/i",

          "container": {
            "docker": {
              "image": "NAME:VERSION1",
              "otherStuff": {}
            }
          }
        }
      ]
    }

  ]
}
最佳答案
这可以通过创建一个符合ID的对象的镜头,然后可以与其他镜头组合以向下钻取图像字段.

首先,我们可以创建一个镜头,将重点放在与某个谓词匹配的数组的元素上(注意:如果保证匹配列表的至少一个元素,这只会是一个有效的镜头)

//:: (a -> Boolean) -> Lens [a] a
const lensMatching = pred => (toF => entities => {
    const index = R.findIndex(pred, entities);
    return R.map(entity => R.update(index, entity, entities),
                 toF(entities[index]));
});

请注意,我们在此手动构造镜头,而不是使用R.lens来保存重复找到与谓词匹配的项目的索引.

一旦我们有了这个功能,我们可以构造一个匹配给定ID的镜头.

//:: String -> Lens [{ id: String }] { id: String }
const lensById = R.compose(lensMatching, R.propEq('id'))

然后,我们可以将所有镜头组合在一起,以瞄准图像场

const imageLens = R.compose(
  R.lensProp('groups'),
  lensById('/1/B'),
  R.lensProp('apps'),
  lensById('/1/B/i'),
  R.lensPath(['container', 'docker', 'image'])
)

哪些可以用来更新数据对象,如下所示:

set(imageLens, 'NAME:VERSION2', data)

如果您想要声明一个专注于图像字符串版本的镜头,您可以再进一步.

const vLens = R.lens(
  R.compose(R.nth(1), R.split(':')),
  (version, str) => R.replace(/:.*/, ':' + version, str)
)

set(vLens, 'v2', 'NAME:v1') // 'NAME:v2'

然后可以将其附加到imageLens的组合,以定位整个对象中的版本.

const verLens = compose(imageLens, vLens);
set(verLens, 'VERSION2', data);

转载注明原文:javascript – Ramda js:具有嵌套数组对象的深层嵌套对象的镜头 - 代码日志