更新ImmutableJS映射
我试图根据一些传入的分页数据更新Immutable.Map
,在我的数据结构中构建*索引。更新ImmutableJS映射
传入的数据是这样的:
[
{
identifier: ADFASD,
tags: [ tag1, tag2]
}, {
identifier: GGHYX,
tags: [ tag2, tag3]
},
]
所需的结果
{
taggedArticleList: {
tag1: [ADFASD],
tag2: [ADFASD, GGHYX],
tag3: [GGHYX],
}
}
目前的JS函数,我重构出(的作品):
let taggedArticleList = {}
action.data.response.results.map((article) => {
article.tags.map((tag) => {
let key = taggedArticleList[tag] || (taggedArticleList[tag] = [];
key.article.push(article.identifier)
});
});
return taggedArticleList
而且我目前的ImmutableJS尝试:
.update('taggedArticleList', taggedArticleList =>
Immutable.Map(
Immutable.fromJS(action.data.response.results).map(
article =>
article.get('tags').map(
tag =>
[
tag,
taggedArticleList.has('tag')
? taggedArticleList.get(tag).push(article.get('identifier'))
: Immutable.List().push(article.get('identifier'))
]
)
)))
我的方法是映射传入的数据“文章”,然后映射通过他们的“标签”,并检查现有的taggedArticleList
是否具有密钥 - 如果它确实向其推送新的标识符,否则创建一个新Immutable.List
然后将其推入。我试图劫持构造函数Immutable.Map
,它接受[key, value]
类型结构作为创建自身的默认方式。
正在返回的数据结构给我一个奇怪的tag<List>
键和List[tag, List[identifier]]
返回形状。任何建议非常感谢。
我假设你输入的数据也不变(这在你尝试的解决方案暗示),即
- 传入整个数据集是不可变列表,
- 每篇文章是一个不可变的地图,并且每个系列的标记都是不可变的列表。
我的答案不包括taggedArticleList
键,因为该级别的对象层次结构不会增加或减少此问题的复杂性。我假设你已经包含了它,因为它对于你的特定用例很重要,但是对于这个答案只是额外的混乱。
注意,在下面的代码,蓄能器为reduce
功能,即jsMap
,是一个正常的JavaScript地图对象,不的不可变映射对象,即jsMap
是可变的。这种可变性对于此解决方案的工作是必需的,并且(我相信)不违反使用不可变数据的原则,因为它只是在处理原始传入数据期间使用的中间变量,并且最终转换为不可变地图。
如上所述,此解决方案假定您的传入数据也是不可变的。但是,如果它只是“正常”(可变的)JavaScript对象数据,则您需要做的唯一一件事就是将article.get('tags')
更改为article.tags
,并将article.get('identifier')
更改为article.identifier
。
const incoming = Immutable.List([
Immutable.Map({
identifier: 'ADFASD',
tags: Immutable.List([ 'tag1', 'tag2'])
}),
Immutable.Map({
identifier: 'GGHYX',
tags: Immutable.List([ 'tag2', 'tag3'])
}),
]);
const updated = Immutable.Map(
incoming.reduce((jsMap, article) => {
article.get('tags').forEach(tag => {
jsMap.set(tag, Immutable.List([
...(jsMap.has(tag) ? jsMap.get(tag) : []),
article.get('identifier')
]));
});
return jsMap;
}, new Map()) // NOTE: this is a regular JavaScript map, NOT an Immutable map
);
console.log(updated);
// console output: Map { "tag1": List [ "ADFASD" ], "tag2": List [ "ADFASD", "GGHYX" ], "tag3": List [ "GGHYX" ] }
正如一个侧面说明,也请注意,在你原来的解决方案,无论是原工作的JavaScript代码和非工作不可变的代码,我想你使用map
不当,即使在第一情况下,你最终得到你想要的解决方案。 map
是一个函数,用于返回一个数组,其中每个元素对应于原始数组中的元素。您正在使用它来按顺序获取每个元素,但只需使用该元素修改其他数据而不从该函数返回任何内容。事实上,你想要的最终结果是而不是具有映射(即对应)到原始数组的数组元素。事实上,结果甚至不是一个数组,它是一个对象(或者更准确地说,一个Map ...我知道,它变得混乱)。我认为在这种情况下,你可能应该使用类似forEach
而不是map
。这段时间你的代码工作,但以这种方式使用map
函数可能会导致未来的混淆/错误。你使用它的方式不是非法的,并且如你所示,可以工作。但是,这不是打算如何使用map
。只是想我会给你一个提醒。