【问题标题】:How to simplify javascript nested array with map(), reduce(), and filter()?如何使用 map()、reduce() 和 filter() 简化 javascript 嵌套数组?
【发布时间】:2019-06-25 21:24:53
【问题描述】:

首先,我是 Javascript、ES6 等的新手,我来自 Java 背景。 我有一个复杂的 javascript 数组结构(下面给出的示例), 我正在尝试将此数组转换为映射(类似于 Java 的键值对类型),键是权限名称(例如 KEY-1、KEY-2、KEY-3、KEY-4、KEY- 5 关于下面的 javascript 数组示例),而 value 是实际权限的逗号分隔值。我可以通过通过嵌套数组循环 b 来实现它,但是循环是我在这里试图避免的,并且想要使用 map()/reduce()/filter()

以下是地图应如何包含数据的示例。由于 KEY-2 存在于两个数组中,因此它们将被覆盖为一个(这非常好)

KEY-1 = ["Roles.Create","Roles.Edit"]
KEY-2 = ["API-Admin.Create","API-Admin.Edit","API-Admin.Read"]
KEY-3 = ["Roles.Create","Roles.Edit"]
KEY-4 = ["Users.Read"]      
KEY-5 = ["Roles.Create","Roles.Edit"]

Javascript 数组

const teamArr = [
  {
    "name":"Team1",
    "accountId":"Billing",
    "teamId":"12345",
    "permissions": {
        "KEY-1": [
            "Roles.Create",
            "Roles.Edit"
        ],
        "KEY-2": [
            "API-Admin.Create",
            "API-Admin.Edit",
            "API-Admin.Read"
        ],
        "KEY-3": [
          "Roles.Create",
          "Roles.Edit"
        ]
     }
   },
   {
     "name":"Team2",
     "accountId":"Sales",
     "teamId":"6789",
     "permissions": {
         "KEY-4": [
             "Users.Read"
         ],
         "KEY-2": [
            "API-Admin.Create",
            "API-Admin.Edit",
            "API-Admin.Read"
        ],
         "KEY-5": [
           "Roles.Create",
           "Roles.Edit"
         ]
      }
   }
]

KEY-1、KEY-2、KEY-3、KEY-4、KEY-5 等都是动态生成的,所以我不能将这些键名硬编码到我的代码中(如 KEY-1、KEY-2 等)。 )

我关注了这个帖子https://www.freecodecamp.org/news/15-useful-javascript-examples-of-map-reduce-and-filter-74cbbb5e0a1f/ 以下是我尝试过的,但我想,我正在努力在复杂的 javascript 数组上正确使用 sort()/reduce()。我更喜欢普通的 Javascript/ES6 解决方案(没有 JQuery pls)。

const sorted = test.sort((a, b) => a.permissions - b.permissions);
// Using reduce:
dict = sorted.reduce(
    (dict, el, index) => (dict[el.permissions] = sorted.length - index, dict),
    {}
);

console.log(dict)

这里的任何帮助将不胜感激。谢谢

【问题讨论】:

    标签: javascript arrays object ecmascript-6


    【解决方案1】:

    由于您不需要担心其他键/值,因此您需要首先创建一个包含所有 permissions 对象的数组。然后从该数组中提取属性,使用 Set 保持数组的唯一性:

    const teamArr = [{"name":"Team1","accountId":"Billing","teamId":"12345","permissions":{"KEY-1":["Roles.Create","Roles.Edit"],"KEY-2":["API-Admin.Create","API-Admin.Edit","API-Admin.Read"],"KEY-3":["Roles.Create","Roles.Edit"]}},{"name":"Team2","accountId":"Sales","teamId":"6789","permissions":{"KEY-4":["Users.Read"],"KEY-2":["API-Admin.Create","API-Admin.Edit","API-Admin.Read"],"KEY-5":["Roles.Create","Roles.Edit"]}}];
    const res = teamArr.flatMap(({ permissions }) => Object.entries(permissions)).reduce((a, [k, v]) => ((a[k] = [...new Set(((a[k] = a[k] || []).push(...v), a[k]))], a)), {});
    console.log(res);
    .as-console-wrapper { max-height: 100% !important; top: auto; }

    更详细的版本:

    const teamArr = [{"name":"Team1","accountId":"Billing","teamId":"12345","permissions":{"KEY-1":["Roles.Create","Roles.Edit"],"KEY-2":["API-Admin.Create","API-Admin.Edit","API-Admin.Read"],"KEY-3":["Roles.Create","Roles.Edit"]}},{"name":"Team2","accountId":"Sales","teamId":"6789","permissions":{"KEY-4":["Users.Read"],"KEY-2":["API-Admin.Create","API-Admin.Edit","API-Admin.Read"],"KEY-5":["Roles.Create","Roles.Edit"]}}];
    const permissions = teamArr.map(({ permissions }) => permissions);
    const res = permissions.flatMap(Object.entries).reduce((a, [k, v]) => {
      a[k] = a[k] || [];
      a[k].push(...v);
      a[k] = [...new Set(a[k])];
      return a;
    }, {});
    console.log(res);
    .as-console-wrapper { max-height: 100% !important; top: auto; }

    【讨论】:

    • 谢谢杰克。您的两种解决方案都像一个魅力。非常感谢您的帮助。
    • 没问题@JameelKhan,总是乐于提供帮助。如果我的回答解决了您的问题,请将其标记为已接受。
    【解决方案2】:

    您可以结合使用flatMap 和reduce(尽管并非所有浏览器都支持flatMap):

    const teamArr = [{
        "name": "Team1",
        "accountId": "Billing",
        "teamId": "12345",
        "permissions": {
          "KEY-1": [
            "Roles.Create",
            "Roles.Edit"
          ],
          "KEY-2": [
            "API-Admin.Create",
            "API-Admin.Edit",
            "API-Admin.Read"
          ],
          "KEY-3": [
            "Roles.Create",
            "Roles.Edit"
          ]
        }
      },
      {
        "name": "Team2",
        "accountId": "Sales",
        "teamId": "6789",
        "permissions": {
          "KEY-4": [
            "Users.Read"
          ],
          "KEY-2": [
            "API-Admin.Create",
            "API-Admin.Edit",
            "API-Admin.Read"
          ],
          "KEY-5": [
            "Roles.Create",
            "Roles.Edit"
          ]
        }
      }
    ]
    
    const result = teamArr
      .flatMap(t => Object.entries(t.permissions))
      .reduce((acc, [key, permissions]) => {
        acc[key] = acc[key] || [];
        acc[key].push(...permissions.filter(p => !acc[key].includes(p)));
        return acc;
      }, {});
      
    console.log(result);

    如果某个键的权限数组可能非常大,您还可以考虑在累加器中的每个键旁边使用Set。

    【讨论】:

    • 感谢滑块,感谢您的帮助 :-)
    【解决方案3】:
    const teamArr = [
      {
        "name":"Team1",
        "accountId":"Billing",
        "teamId":"12345",
        "permissions": {
            "KEY-1": [
                "Roles.Create",
                "Roles.Edit"
            ],
            "KEY-2": [
                "API-Admin.Create",
                "API-Admin.Edit",
                "API-Admin.Read"
            ],
            "KEY-3": [
              "Roles.Create",
              "Roles.Edit"
            ]
         }
       },
       {
         "name":"Team2",
         "accountId":"Sales",
         "teamId":"6789",
         "permissions": {
             "KEY-4": [
                 "Users.Read"
             ],
             "KEY-2": [
                "API-Admin.Create",
                "API-Admin.Edit",
                "API-Admin.Read"
            ],
             "KEY-5": [
               "Roles.Create",
               "Roles.Edit"
             ]
          }
       }
    ];
    
    
    
    function extractPermissions(obj) {
        const perms = {};
        obj.forEach(entry => {
            if (!entry['permissions']) {
                return;
            }
            Object.keys(entry.permissions).forEach(key => {
                if (!perms[key]) {
                    perms[key] = [];
                }
                entry.permissions[key].forEach(value => {
                    if (!perms[key].some(val => val === value)) {
                        perms[key].push(value);
                    }
                });
            });
        });
        return perms;
    }
    console.log(JSON.stringify(extractPermissions(teamArr), null, 2));
    

    【讨论】:

    • 感谢您的帮助 René Datenschutz。唯一的问题是该解决方案使用了我试图避免的循环,但我想这是使用普通的 JS/ES6,它不会有任何浏览器版本依赖性。尽管如此,在这里感谢您的帮助:-)
    猜你喜欢
    • 2021-06-06
    • 2021-06-20
    • 2021-10-30
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 2017-11-05
    • 1970-01-01
    相关资源
    最近更新 更多