我正在尝试根据一些传入的分页数据更新Immutable.Map
,在我的数据结构中构建顶级索引。
传入的数据如下所示:
[
{
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]]
返回形状。任何建议都非常感激。
答案 0 :(得分:1)
我假设您的传入数据也是不可变的(您在尝试的解决方案中暗示),即
我的答案不包括taggedArticleList
键,因为该级别的对象层次结构不会增加或消除此问题的复杂性。我假设你把它包括在内,因为它对你的特定用例很重要,但它只是这个答案的额外混乱。
请注意,在下面的代码中,reduce
函数的累加器,即jsMap
,是普通 JavaScript Map对象,不是不可变的Map对象,即jsMap
是可变的。此解决方案需要这种可变性,并且(我相信)不违反使用不可变数据的原则,因为它只是在处理原始传入数据期间使用的中间变量,并且最终转换为Immutable地图。
如上所述,此解决方案假定您的传入数据也是不可变的。但是,如果它只是&#34;正常&#34; (可变)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
是一个函数,用于返回一个数组,其中每个元素对应于原始数组中的元素。您正在使用它来顺序获取每个元素,但之后只需使用该元素来修改其他数据,而无需从该函数返回任何内容。实际上,您想要的最终结果 not 具有映射(即对应)原始数组的数组元素。事实上,结果甚至不是一个数组,它是一个对象(或者更确切地说,一个地图......我知道,它会让人感到困惑)。我认为在这种情况下,您可能应该使用类似forEach
而不是map
的内容。您的代码这次工作正常,但以这种方式使用map
函数可能会导致将来出现混淆/错误。你使用它的方式并不违法,而且,如你所说,可以工作。但是,并不是map
打算如何使用。只是想我会就此向你提出一个单挑。