[英]Nested array mapping and filtering in javascript
I am designing a system and I have some bottlenecks.我正在设计一个系统,但我遇到了一些瓶颈。
I have user array such like that:我有这样的用户数组:
const users = [
{
name: "Jack",
workspaces: [
{
_id: "61216512315615645jbk",
permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"],
},
{
_id: "41ss16512315615645bk",
permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"],
},
],
},
{
name: "Joe",
workspaces: [
{
_id: "71216512315615645jbk",
permissions: ["CAN_DELETE_WORKSPACE"],
},
],
},
];
And I have activeWorkspace object such like that:我有 activeWorkspace object 像这样:
const activeWorkspace = {
name: "W1",
_id: "61216512315615645jbk",
};
I need to filter the objects in the users array whose workspace _id is equal to activeWorkspace _id.我需要过滤用户数组中工作空间_id 等于activeWorkspace _id 的对象。
Output must be like that: Output 必须是这样的:
{
name: "Jack",
workspaces: [
{
_id: "61216512315615645jbk",
permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"],
},
{
_id: "41ss16512315615645bk",
permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"],
},
],
}
How can I do that?我怎样才能做到这一点?
In addition: If we want to return an array, not an object, how should we do it?另外:如果我们要返回一个数组,而不是一个object,我们应该怎么做呢? Like that:像那样:
[{
name: "Jack",
workspaces: [
{
_id: "61216512315615645jbk",
permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"],
},
{
_id: "41ss16512315615645bk",
permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"],
},
],
}]
Thanks谢谢
The approach is to use filter() and some() to find what users have the workspace方法是使用 filter() 和 some() 来查找用户拥有哪些工作空间
const users = [ { name: "Jack", workspaces: [ { _id: "61216512315615645jbk", permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"], }, { _id: "41ss16512315615645bk", permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"], }, ], }, { name: "Joe", workspaces: [ { _id: "61216512315615645jbk", permissions: ["CAN_DELETE_WORKSPACE"], }, ], }, ]; const activeWorkspace = { name: "W1", _id: "61216512315615645jbk", }; const active = users.filter(function (user) { return user.workspaces.some( function (workspace) { return workspace._id === activeWorkspace._id; }); }); console.log(active); // Same thing as above, just done without a modern approach const active2 = users.filter(({workspaces}) => workspaces.some(({_id}) => _id === activeWorkspace._id)); console.log(active2);
If there can only be one (your sample data has a typo?) then you can can use find() and some()如果只能有一个(您的示例数据有错字?)那么您可以使用 find() 和 some()
const users = [ { name: "Jack", workspaces: [ { _id: "61216512315615645jbk", permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"], }, { _id: "41ss16512315615645bk", permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"], }, ], }, { name: "Joe", workspaces: [ { _id: "CHANGED_ID", permissions: ["CAN_DELETE_WORKSPACE"], }, ], }, ]; const activeWorkspace = { name: "W1", _id: "61216512315615645jbk", }; const active = users.find(function (user) { return user.workspaces.some( function (workspace) { return workspace._id === activeWorkspace._id; }); }); console.log(active); // Same thing as above, just done without a modern approach const active2 = users.find(({workspaces}) => workspaces.some(({_id}) => _id === activeWorkspace._id)); console.log(active2);
I adjusted the provided data from Joe so he doesn't have permissions我调整了乔提供的数据,所以他没有权限
const users = [{ name: "Jack", workspaces: [{ _id: "61216512315615645jbk", permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"], }, { _id: "41ss16512315615645bk", permissions: ["CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT"], }, ], }, { name: "Joe", workspaces: [{ _id: "61216512315615645bk", permissions: ["CAN_DELETE_WORKSPACE"], }, ], }, ]; const activeWorkspace = { name: "W1", _id: "61216512315615645jbk", }; function findPermittedUser() { return users.filter(user => { let hasPermission = false user.workspaces.forEach(workspace => { if (activeWorkspace._id == workspace._id) { hasPermission = true } }) return hasPermission }) } console.log(findPermittedUser())
You can use map
and filter
to "filter" out the unwanted ids from the users
object.您可以使用map
和filter
器从users
object 中“过滤”掉不需要的 ID。 Something like:就像是:
const users = [ { "name": "Jack", "workspaces": [ { "_id": "61216512315615645jbk", "permissions": [ "CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT" ] }, { "_id": "41ss16512315615645bk", "permissions": [ "CAN_DELETE_WORKSPACE", "CAN_EDIT_PROJECT" ] } ] }, { "name": "Joe", "workspaces": [ { "_id": "61216512315615645jbk", "permissions": [ "CAN_DELETE_WORKSPACE" ] } ] } ] const activeWorkspace = { name: "W1", _id: "61216512315615645jbk", }; const filteredUsers = users.map(item => ({ name: item.name, workspaces: item.workspaces.filter(user => user._id === activeWorkspace._id)} )); console.log(filteredUsers);
This should work (tested):这应该有效(经过测试):
const filteredUsers = users.filter(
user => user.workspaces.reduce(
(acc, workspace) => acc || workspace._id === activeWorkspace._id, false)
)
)
Explanation: We are using filter
and reduce
as evident from the code.说明:从代码中可以看出,我们正在使用filter
和reduce
。 What the code is doing is pretty simple, first, we want to apply filter
on the user array.代码所做的非常简单,首先,我们要在用户数组上应用filter
。 Now in the filter, we need to define the logic, which should return true
whenever our condition happens to be true.现在在过滤器中,我们需要定义逻辑,只要我们的条件恰好为真,它就应该返回true
。 Since we have an array of workspaces, we need to iterate over all of them to check if our activeWorkspace._id exists in any of them.由于我们有一个工作区数组,我们需要遍历所有这些以检查我们的 activeWorkspace._id 是否存在于其中任何一个中。 For this, you can use a for loop and return true
when you find it, else return false
if not.为此,您可以使用 for 循环并在找到时返回true
,否则返回false
。 But the functional way of doing it would be to use reduce
and initialize the accumulator with false
.但是这样做的功能性方法是使用reduce
并使用false
初始化累加器。 Every time you access a workspace, you return acc || <our condition>
每次访问工作区时,都会返回acc || <our condition>
acc || <our condition>
. acc || <our condition>
。 Notice how if even once our condition returns true, the accumulator becomes true
for the rest of the execution of reduce
.请注意,即使我们的条件返回 true,对于reduce
执行的 rest,累加器也会变为true
。 This is slightly poor in performance since you are not exiting as soon as you have found your workspace._id as you would have done in case of a for
loop.这在性能上稍差,因为你没有在找到你的 workspace._id 后立即退出,就像你在for
循环的情况下所做的那样。
users.map(u => u.workspaces).flat().filter(w => w._id === activeWorkspaceId);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.