【问题标题】:Create new multidimensional array based on this existing array objec基于此现有数组对象创建新的多维数组
【发布时间】:2018-06-11 04:38:35
【问题描述】:

我被困在这个现有数组对象的基础上构造一个新的多维数组

acl:[
{
   view:true, 
   update:true, 
   remove:true, 
   userId:1, 
   username:"Mike"
},
{
   view:true, 
   update:true, 
   remove:false, 
   userId:2, 
   username:"Joe"
},
{
   view:true, 
   update:false, 
   remove:false, 
   userId:3, 
   username:"Lim"
}
]

新对象将根据布尔属性构造(如果这些布尔属性等于 true)。新数组将如下所示

acl:[
{
view:[
   {username:"Mike", userId:1},
   {username:"Joe", userId:2},
   {username:"Lim", userId:3}
]
update:[
   {username:"Mike", userId:1},
   {username:"Joe", userId:2}
]
remove:[
   {username:"Mike", userId:1}
]

我坚持在迭代中构建逻辑。也许有人可以给我一个提示。

【问题讨论】:

  • 这不是社区为您工作的地方,请展示您所做的工作以及您需要帮助的地方。上面的问题中没有代码,只有在家庭作业中可能会看到的问题。对于一个非常简单的练习

标签: javascript multidimensional-array ecmascript-6


【解决方案1】:

您可以使用reduce 组合成一个数组对象:

const acl=[{view:!0,update:!0,remove:!0,userId:1,username:"Mike"},{view:!0,update:!0,remove:!1,userId:2,username:"Joe"},{view:!0,update:!1,remove:!1,userId:3,username:"Lim"}];

console.log(
  acl.reduce((a, { view, update, remove, userId, username }) => {
    const obj = { username, userId };
    if (view) a.view.push(obj);
    if (update) a.update.push(obj);
    if (remove) a.remove.push(obj);
    return a;
  }, { view: [], update: [], remove: [] })
);

或者,如果用户名/userId对象需要单独引用,可以使用spread:

const acl=[{view:!0,update:!0,remove:!0,userId:1,username:"Mike"},{view:!0,update:!0,remove:!1,userId:2,username:"Joe"},{view:!0,update:!1,remove:!1,userId:3,username:"Lim"}];

console.log(
  acl.reduce((a, { view, update, remove, userId, username }) => {
    const obj = { username, userId };
    if (view) a.view.push({...obj});
    if (update) a.update.push({...obj});
    if (remove) a.remove.push({...obj});
    return a;
  }, { view: [], update: [], remove: [] })
);

【讨论】:

    【解决方案2】:

    通常我不会回答这个问题,但是告诉你使用 reduce 的人数让我很生气。

    最简洁的方法是使用过滤器(如果您只使用查看/更新/删除)。它们实际上描述了您尝试采取的行动。

    const acl2 = {
      view: acl.filter(({view}) => view),
      update: acl.filter(({update}) => update),
      remove: acl.filter(({remove}) => remove),
    };
    

    【讨论】:

    • reduce 到底是什么?根据您的解决方案,它只需要迭代整个列表一次而不是 3 次吗?
    • Reduce 执行速度更快。过滤器可以更快地理解。这些答案都没有使 OP 在如何正确使用社区方面受益。
    • @RobbyCornelissen 如果速度是一个问题,你会使用 for 循环。您永远不会将代码重构为减少以提高速度。两种解决方案都是 O(n)。
    • @david 我同意使用for 循环以获得最佳性能。我确实不会重构代码以使用reduce() 来提高速度,但如果可以一次完成,我也不会编写循环数组三次的代码。两种解决方案的复杂性确实是线性的,但在某些情况下 O(n) 和 O(3n) 之间的差异可能很大。
    • @RobbyCornelissen 如果 n 和 3n 之间的差异很大,那么使用 reduce 和 for 循环之间的差异会更大。 reduce 和 filter 在可读性上的差异是巨大的。将其与使用方法链进行比较,例如 x.map().filter().map(),您不会更喜欢 reduce 吧?
    【解决方案3】:
    const acl = [{"view":true,"update":true,"remove":true,"userId":1,"username":"Mike"},{"view":true,"update":true,"remove":false,"userId":2,"username":"Joe"},{"view":true,"update":false,"remove":false,"userId":3,"username":"Lim"}]
    
    function multi_dim (array) {
    
      const res = {
        view: [],
        update: [],
        remove: []
      }
    
      const keys = Object.keys(array[0])
    
      for (let i = 0; i < array.length; i++) {
        keys.forEach(function (key) {
          if (key !== 'username' && key !== 'userId') {
            if (array[i][key]) {
              res[key].push({
                username: array[i].username,
                userId: array[i].userId
              })
            }
          }
        })
      }
    
      return res
    
    }
    
    let obj = multi_dim(acl) // returns object. Push to array if so desired
    
    console.log(obj)
    
    // => result
    //   {
    //     "view": [
    //       {
    //         "username": "Mike",
    //         "userId": 1
    //       },
    //       {
    //         "username": "Joe",
    //         "userId": 2
    //       },
    //       {
    //         "username": "Lim",
    //         "userId": 3
    //       }
    //     ],
    //     "update": [
    //       {
    //         "username": "Mike",
    //         "userId": 1
    //       },
    //       {
    //         "username": "Joe",
    //         "userId": 2
    //       }
    //     ],
    //     "remove": [
    //       {
    //         "username": "Mike",
    //         "userId": 1
    //       }
    //     ]
    //   }
    

    【讨论】:

      【解决方案4】:

      你可以使用Array.prototype.reduce()如下:

      const permissions = ['view', 'update', 'remove'];
      const output = acl.reduce((a, v) => {
        permissions.forEach(p => {
          if (v[p]) a[p].push({username: v.username, userId: v.userId});
        });
      
        return a;
      }, permissions.reduce((a, p) => ({ ...a, [p]: []}), {}));
      

      const acl = [{
          view: true,
          update: true,
          remove: true,
          userId: 1,
          username: "Mike"
        },
        {
          view: true,
          update: true,
          remove: false,
          userId: 2,
          username: "Joe"
        },
        {
          view: true,
          update: false,
          remove: false,
          userId: 3,
          username: "Lim"
        }];
      
      const permissions = ['view', 'update', 'remove'];
      
      const output = acl.reduce((a, v) => {
        permissions.forEach(p => {
          if (v[p]) a[p].push({username: v.username, userId: v.userId});
        });
        
        return a;
      }, permissions.reduce((a, p) => ({ ...a, [p]: []}), {}));
      
      console.log(output);

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2019-02-28
      相关资源
      最近更新 更多