简体   繁体   English

javascript 中的嵌套数组映射和过滤

[英]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.您可以使用mapfilter器从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.说明:从代码中可以看出,我们正在使用filterreduce 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循环的情况下所做的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM