我有一个看起来像这样的ImmutableJS结构:
let state = fromJS({
// ...
foo: [{
bar: ['id1', 'id2']
},{
bar: ['id2', 'id3']
}]
});
我想要映射foo
并针对每个项目,将相关的bar
与另一个ID数组进行过滤,以排除(idsToExclude
)。
我想出了这个:
const idsToExclude = ['id3', 'id4'];
state = {
...state,
foo: state.get('foo').map((i) =>
i.set(['bar'], i.get(['bar']
.filterNot(b => idsToExclude.some(id => id === b))))
};
是否有更好,更惯用或更简洁的方式?
我问,因为这看起来很冗长。
答案 0 :(得分:0)
我认为你可以使用.update
让它变得更清洁,尽管这仍然相当长。您还可以将.some(id => id === b)
简化为.contains(b)
。
state = state.update('foo', foo =>
foo.map(item =>
item.update('bar',
bar => bar.filterNot(
id => idsToExclude.contains(id)))));
答案 1 :(得分:0)
现有代码存在一些问题:
state = {...state}
正在创建一个普通的JS对象,而不是Immutable.js Map
,并且它不会正确地将新的foo
合并到state
的字段中。 get
和set
只接受一个key
,而不是数组。要将密钥数组用作路径,请使用getIn
或setIn
。如果您可以在数据结构中使用不可变Set
而不是Lists
,那么您可以使用subtract
之类的集合操作来简化代码:
import {fromJS, Set} from 'immutable'
const initState = fromJS({
// ...
foo: [
{bar: Set(['id1', 'id2'])},
{bar: Set(['id2', 'id3'])}
]
})
const idsToExclude = fromJS(['id3', 'id4'])
const finalState = initState.update('foo', foo =>
foo.map(element =>
element.update('bar', set =>
set.subtract(idsToExclude)
)
)
)
即使没有在您的数据结构中存储Set
,您也可以在突变期间暂时使用它们:
const initState = fromJS({
// ...
foo: [
{bar: ['id1', 'id2']},
{bar: ['id2', 'id3']}
]
})
const idsToExclude = fromJS(['id3', 'id4'])
const finalState = initState.update('foo', foo =>
foo.map(element =>
element.update('bar', list =>
list.toSet().subtract(idsToExclude).toList()
)
)
)