【问题标题】:Update nested values based on a condition using Ramda使用 Ramda 根据条件更新嵌套值
【发布时间】:2023-04-03 13:09:01
【问题描述】:

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

我想用名称blah 更新C 中对象的 value 属性

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

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

理想情况下,我会喜欢返回新对象的东西。

const res = fn(o)


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

【问题讨论】:

  • 这就是为什么正确的类型比正确的算法更重要的原因:你选择了奇怪的结构,难怪修改它需要奇怪的代码。
  • 这是从 api 调用返回的数据。我可以将其拆分为子元素并将其缝合在一起,但更新结构内的值肯定是可以以合理的方式完成的吗?
  • 是的,以命令式的方式进行:const obj = o.A.B.C.find(nested => nested.name === 'blah'); if (obj !== undefined) { obj.value = 'vtha'; } 它易于阅读和维护。如有必要 - 将其包装在一个函数中以看起来“实用”。
  • @zerkms 这就是为什么正确的类型比正确的算法更重要的原因。 事实上,另外:正确的类型自然会导致正确的算法。我们需要更多地讨论 Javascript 中的类型。

标签: javascript functional-programming ramda.js


【解决方案1】:

如果你想以不可变的方式做到这一点,那就是

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
)

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

【讨论】:

  • when 是当 else 函数为 identity 时的简洁简写
【解决方案2】:

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

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);

【讨论】:

  • var pred = a => a.filter(o => o.name === 'blah');。更容易阅读、更快、消耗更少的内存,vanilla JS 也是如此。
【解决方案3】:

要更新对象中的数组,我们需要数组的路径。然后我们可以用一个镜头和一个辅助函数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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 2021-12-08
    • 2018-11-18
    • 2017-06-09
    相关资源
    最近更新 更多