使用 Ramda 根据条件更新嵌套值

Update nested values based on a condition using Ramda

我正在尝试使用 Ramda 更新嵌套对象结构中数组中的值。

我想用名称 blah

更新 C 中对象的值属性
const o = {
  A: {
    B: {
      C: [
        {name: 'blah', value: 'blah'},
        {name: 'vtha', value: 'blah'},
      ]
    }
  }
}

我一直在使用镜头,但它看起来很冗长,我认为我做错了。

理想情况下,我会喜欢 returns 新对象。

const res = fn(o)


{
  A: {
    B: {
      C: [
        {name: 'blah', value: 'vtha'}
        {name: 'vtha', value: 'blah'},
      ]
    }
  }
}

您可以尝试使用过滤器,我在下面写了一个示例。

const o = {
  A: {
    B: {
      C: [
        {name: 'blah', value: 'blah'},
        {name: 'vtha', value: 'blah'},
      ]
    }
  }
};

var pred = R.filter(R.where({name: R.contains('blah')}));

pred(o.A.B.C);

如果你想以不可变的方式来做它就像

const fn = over(
  R.lensPath(['A', 'B', 'C']),
  R.map(
    o => o.name === 'blah' ? R.assoc('value', 'vtha', o): o
  )
)

Demo.

如果您想避免手动定义函数,您可以将映射函数替换为

R.ifElse(
  R.propEq('name', 'blah'),
  R.assoc('value', 'blah'),
  R.identity
)

但是恕我直言,三元运算符在这里看起来更具可读性。

要更新对象中的数组,我们需要数组的路径。然后我们可以用镜头和辅助函数adjustIfSatisfies

更新结果

const { propEq, identity, over, assoc, curry, lensPath, map, ifElse } = R
const o = {
  A: {
    B: {
      C: [
        {name: 'blah', value: 'blah'},
        {name: 'vtha', value: 'blah'},
      ]
    }
  }
}

const adjustIfSatisfies = curry(
  (pred, updateFn, samples) => {
    return map(ifElse(pred, updateFn, identity), samples)
  }
)

const result = over(
  lensPath(['A', 'B', 'C']), 
  adjustIfSatisfies(
    propEq('name', 'blah'), 
    assoc('value', 'vtha')
  ),
  o
)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>