使用 Ramda 进行嵌套列表过滤和条件对象映射
Nested list filtering & conditional object mapping with Ramda
我正在努力思考 Ramda.js 但我卡住了。我有一个看起来像这样的数组:
const state = [
{
itemId: 112,
animations: [{id: 1}, {id:2}],
classes: ['animated']
},
{
itemId: 121,
animations: [{id:2}],
classes: ['animated']
}
]
我的目标是创建一个函数,其中
removeAnimation(121, 2, state);
...会 return:
const state = [
{
itemId: 112,
animations: [{id: 1}, {id:2}],
classes: ['animated']
},
{
itemId: 121,
animations: [],
classes: []
}
]
所以函数根据指定的id
移除动画obj,里面有指定的itemId
的对象,如果animations
数组中没有更多的对象,它也会删除 classes
列表中的 animated
字符串。
这是我的进展:
const removeAnimationFromItem = R.curry((itemId, animId, state) => {
return R.map(
R.when(
R.propEq('itemId', itemId), [--This is where I'm stuck--]
), state)
})
感谢您的宝贵时间。
我认为这里有一个重要的问题,即您是否真的想要 Ramda 的行为。如果我们用 Ramda 做这样的事情,它不会改变你的数据。它将 return 新对象与您的原件共享它们可以共享的内容,但您的原件仍将保持原样。 Ramda 团队(免责声明:我是 Ramda 的作者之一)认为这是一件非常好的事情。但有时它可能会令人惊讶。
Ramda 没有任何现成的解决方案可以使这变得容易。如果我要这样做,我可能首先将其分解为两个步骤:删除目标动画,然后更新所有项目的 类 属性。我觉得这个更容易思考。如果结果证明有性能问题,我可能会考虑将它们结合起来。
这是一种方法:
const {findIndex, propEq, adjust, evolve, remove, without, pipe, map} = R
const removeOneAnimation = (itemId, animId, state) => {
const itemIdx = findIndex(propEq('itemId', itemId), state)
if (itemIdx < 0) {return state}
const animIdx = findIndex(propEq('id', animId), state[itemIdx].animations)
if (animIdx < 0) {return state}
return adjust(evolve({animations: remove(animIdx, 1)}) , itemIdx, state)
}
const updateAnimClass = (item) => item.animations.length === 0 ? evolve({classes: without(['animated'])}, item) : item
const removeAnimations = pipe(
removeOneAnimation,
map(updateAnimClass)
)
const state = [{"animations": [{"id": 1}, {"id": 2}], "classes": ["animated"], "itemId": 112}, {"animations": [{"id": 2}], "classes": ["animated"], "itemId": 121}]
const newState = removeAnimations(121, 2, state)
console.log(newState)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
请注意,此处的一些 Ramda 代码并没有提供很大的提升。例如,这个:
const itemIndex = findIndex(propEq('itemId', itemId), state)
可以写成
const itemIndex = state.findIndex(item => item.itemId === itemId)
但是其他一些功能,例如evolve
, adjust
, remove
, and without
做的很多。如果您希望 Ramda 将数据视为不可变的方法,这些方法非常强大。
我正在努力思考 Ramda.js 但我卡住了。我有一个看起来像这样的数组:
const state = [
{
itemId: 112,
animations: [{id: 1}, {id:2}],
classes: ['animated']
},
{
itemId: 121,
animations: [{id:2}],
classes: ['animated']
}
]
我的目标是创建一个函数,其中
removeAnimation(121, 2, state);
...会 return:
const state = [
{
itemId: 112,
animations: [{id: 1}, {id:2}],
classes: ['animated']
},
{
itemId: 121,
animations: [],
classes: []
}
]
所以函数根据指定的id
移除动画obj,里面有指定的itemId
的对象,如果animations
数组中没有更多的对象,它也会删除 classes
列表中的 animated
字符串。
这是我的进展:
const removeAnimationFromItem = R.curry((itemId, animId, state) => {
return R.map(
R.when(
R.propEq('itemId', itemId), [--This is where I'm stuck--]
), state)
})
感谢您的宝贵时间。
我认为这里有一个重要的问题,即您是否真的想要 Ramda 的行为。如果我们用 Ramda 做这样的事情,它不会改变你的数据。它将 return 新对象与您的原件共享它们可以共享的内容,但您的原件仍将保持原样。 Ramda 团队(免责声明:我是 Ramda 的作者之一)认为这是一件非常好的事情。但有时它可能会令人惊讶。
Ramda 没有任何现成的解决方案可以使这变得容易。如果我要这样做,我可能首先将其分解为两个步骤:删除目标动画,然后更新所有项目的 类 属性。我觉得这个更容易思考。如果结果证明有性能问题,我可能会考虑将它们结合起来。
这是一种方法:
const {findIndex, propEq, adjust, evolve, remove, without, pipe, map} = R
const removeOneAnimation = (itemId, animId, state) => {
const itemIdx = findIndex(propEq('itemId', itemId), state)
if (itemIdx < 0) {return state}
const animIdx = findIndex(propEq('id', animId), state[itemIdx].animations)
if (animIdx < 0) {return state}
return adjust(evolve({animations: remove(animIdx, 1)}) , itemIdx, state)
}
const updateAnimClass = (item) => item.animations.length === 0 ? evolve({classes: without(['animated'])}, item) : item
const removeAnimations = pipe(
removeOneAnimation,
map(updateAnimClass)
)
const state = [{"animations": [{"id": 1}, {"id": 2}], "classes": ["animated"], "itemId": 112}, {"animations": [{"id": 2}], "classes": ["animated"], "itemId": 121}]
const newState = removeAnimations(121, 2, state)
console.log(newState)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
请注意,此处的一些 Ramda 代码并没有提供很大的提升。例如,这个:
const itemIndex = findIndex(propEq('itemId', itemId), state)
可以写成
const itemIndex = state.findIndex(item => item.itemId === itemId)
但是其他一些功能,例如evolve
, adjust
, remove
, and without
做的很多。如果您希望 Ramda 将数据视为不可变的方法,这些方法非常强大。