javascript - 比较两个具有共同字段的数组,然后推送到具有相应分组字段的新数组
问题描述
这里的一般编程问题。
我有这个数组叫SPACES
[
{
_id: 5e1c4689429a8a0decf16f69,
challengers: [
5dfa24dce9cbc0180fb60226,
5dfa26f46719311869ac1756,
5dfa270c6719311869ac1757
]
},
{
_id: 5e1c4eb9c9461510407d5e81,
challengers: [ 5dfa24dce9cbc0180fb60226, 5dfa26f46719311869ac1756 ],
}
]
这个数组叫做USERS
[
{
_id: 5dfa24dce9cbc0180fb60226,
name: 'Account 1',
email: 'account1@gmail.com',
spaces: [ 5e1c4689429a8a0decf16f69, 5e1c4eb9c9461510407d5e81 ],
},
{
_id: 5dfa26f46719311869ac1756,
name: 'Account 2',
email: 'account2@gmail.com',
spaces: [ 5e1c4689429a8a0decf16f69, 5e1c4eb9c9461510407d5e81 ]
},
{
_id: 5dfa270c6719311869ac1757,
name: 'Account 3',
email: 'account3@gmail.com',
spaces: [ 5e1c4689429a8a0decf16f69 ]
}
]
我想要做的是通过两者,而不是让SPACES.challengers
数组只是IDS
,我希望数组包含每个USER
对象。
例如,如果USER
有一个 ID 在SPACES.challengers
数组中,则将用户推送到该数组中(这将是整个对象)。
到目前为止,我已经尝试过了(我还不是很好):
users.map( ( user ) => {
spaces.map( ( space ) => {
if ( user.spaces.includes( space._id ) ) {
space.challengers.push(user)
}
} );
} );
但是,我没有进入 IF 块。(即使我这样做了,也不确定它是否会起作用,或者这是否是如何做到的)。做双重地图感觉很奇怪,因为我得到了这么多的迭代,而且它重复了我的推送(因为我没有逻辑来查看它是否刚刚被推送)。
解决方案
假设数组中的每个条目Users
都有一个唯一的 ID,我们可以构建一个Hashmap
来存储(id, index)
对,以便Users
在遍历数组时有效地从数组中搜索 ID Spaces
。
let spaces = [{_id: '5e1c4689429a8a0decf16f69',challengers: ['5dfa24dce9cbc0180fb60226', '5dfa26f46719311869ac1756', '5dfa270c6719311869ac1757']},{_id: '5e1c4eb9c9461510407d5e81',challengers: [ '5dfa24dce9cbc0180fb60226', '5dfa26f46719311869ac1756' ],}]
let users = [{_id: '5dfa24dce9cbc0180fb60226',name: 'Account 1',email: 'account1@gmail.com',spaces: [ '5e1c4689429a8a0decf16f69', '5e1c4eb9c9461510407d5e81' ],},{_id: '5dfa26f46719311869ac1756',name: 'Account 2',email: 'account2@gmail.com',spaces: [ '5e1c4689429a8a0decf16f69', '5e1c4eb9c9461510407d5e81' ]},{_id: '5dfa270c6719311869ac1757',name: 'Account 3',email: 'account3@gmail.com',spaces: [ '5e1c4689429a8a0decf16f69' ]}]
let IDIndexMapping = {} // To store (_id, index) pairs, in order to improve search efficiency
for(let index in users) // Iterate through Users array using index
IDIndexMapping[users[index]._id] = index; // store (_id, index) pair in IDIndexMapping
// I'm avoiding using `map` and using vanilla `for` loop for space efficiency
// as map returns a new array but with `for` loop, we can perform changes in-place
for(let outerIndex in spaces){ // Iterate through `spaces` array using index
let challengers = spaces[outerIndex].challengers; // Get challengers array
for(let innerIndex in challengers){ // Iterate through challengers array using index
let ID = challengers[innerIndex]; // Get ID
if(ID in IDIndexMapping) // If ID exists in IDIndexMapping
spaces[outerIndex].challengers[innerIndex] = users[IDIndexMapping[ID]]; // Change ID to actual User object
}
}
console.log(spaces)
输出
[ { _id: '5e1c4689429a8a0decf16f69',
challengers: [ [Object], [Object], [Object] ] },
{ _id: '5e1c4eb9c9461510407d5e81',
challengers: [ [Object], [Object] ] } ]
推荐阅读
- java - 当我不知道文件流在哪里打开时,有什么方法可以关闭它?
- wpf - 如何防止使用 GridView 列调整 Listview 的大小
- react-native - 反应本机路由器通量;加载回上一个组件很慢
- security - 在标头中包含 xsrf 令牌的最佳方法是 cookie 是 httpOnly
- sql - 如何查询范围为每个关联的最新记录的记录
- maven - 有人可以使用 GitLab Maven 存储库组级别端点吗?
- c# - Identityserver4 未发送 access_token
- python - 一种将重复项转换为 Python 索引的优雅方法?
- r - with() 函数内的脚本没有数据帧输出
- docker - 已弃用字段 [disable_coord],替换为 [disable_coord 已删除]