【问题标题】:group and filter and array of objects using VanillaJS使用 VanillaJS 对对象进行分组、过滤和数组
【发布时间】:2017-12-08 14:44:54
【问题描述】:

我有下表,其中包含一些对象:

var data = [
    {
        "userRoleId": 1,
        "userId": 1,
        "roleId": 1,
        "organizationId": "ORG_01",
        "roleTitle": "Admin",
        "organizationTitle": "Organization 01",
        "startDate": "2017-11-15",
        "endDate": "2017-11-15",
        "automatic": false,
        "useDate": "2017-11-15"
    },
    {
        "userRoleId": 2,
        "userId": 1,
        "roleId": 2,
        "organizationId": "ORG_01",
        "roleTitle": "Agent",
        "organizationTitle": "Organization 01",
        "startDate": "2017-11-15",
        "endDate": "2017-11-15",
        "automatic": true,
        "useDate": "2017-11-15"
    },
    {
        "userRoleId": 4,
        "userId": 1,
        "roleId": 4,
        "organizationId": "ORG_02",
        "roleTitle": "Referent",
        "organizationTitle": "Organization 02",
        "startDate": "2017-11-15",
        "endDate": "2017-11-15",
        "automatic": true,
        "useDate": "2017-11-15"
    },
    {
        "userRoleId": 5,
        "userId": 1,
        "roleId": 2,
        "organizationId": "ORG_02",
        "roleTitle": "Agent",
        "organizationTitle": "Organization 02",
        "startDate": "2017-11-15",
        "endDate": "2017-11-15",
        "automatic": true,
        "useDate": "2017-11-15"
    }
];

我想要做的是使用对象属性"organizationId""organizationTitle" 对这些对象进行分组,所以我尝试使用"organizationId" 将它们分组如下:

var filtered = data.reduce(function(accumulator, currentValue) {
    (accumulator[currentValue['organizationId']] = accumulator[currentValue['organizationId']] || []).push(currentValue);
    return accumulator;
  }, {});

这将生成一个带有键的对象,该键具有用于分组的每个 "organizationId" 的值,并将分组数据作为其值。

然后我想为每个用于分组的 "organizationId" 创建一个对象,该对象将具有三个属性:id 将具有 "organizationId" 的值,title 将具有 "organizationTitle" 的值和roles 是一个数组。

该数组将包含每个分组对象的对象,该对象将具有两个属性:id 的值为 "roleId"title 的值为 "roleTitle"

所以结果应该是这样的:

[
    { 
        id: 'ORG_01',
        lib: 'Organization 01',
        roles: [
            {
                id: 1,
                title: 'Admin'
            },
            {
                id: 2,
                title: 'Agent'
            }
        ] 
    },
      { 
        id: 'ORG_02',
        lib: 'Organization 02',
        roles: [
            {
                id: 4,
                title: 'Referent'
            },
            {
                id: 2,
                title: 'Agent'
            }
        ] 
    }
]

所以我做了以下工作,我得到了预期的结果:

var organizations = [];

for(var i in filtered){
    var obj = {};
    obj.id = i;

    var roles = [];
    filtered[i].forEach(function(el){
        roles.push({'id' : el.roleId, 'lib': el.roleTitle})
        obj.lib = el.organizationTitle;
    });
    obj.roles = roles;
    organizations.push(obj);
}

console.log(organizations);

如您所见,我为此使用了太多代码,首先我使用了 reduce 函数,然后使用了一个 forEeach 并将其插入另一个 forEach。

难道没有一种简单的方法可以使用 vanillaJS (ES5) 和最少的代码吗?

提前致谢。

【问题讨论】:

    标签: javascript filtering grouping


    【解决方案1】:

    您可以使用array#reduce 收集您的所有信息。

    var data = [ { "userRoleId": 1, "userId": 1, "roleId": 1, "organizationId": "ORG_01", "roleTitle": "Admin", "organizationTitle": "Organization 01", "startDate": "2017-11-15", "endDate": "2017-11-15", "automatic": false, "useDate": "2017-11-15" }, { "userRoleId":2, "userId": 1, "roleId": 2, "organizationId": "ORG_01", "roleTitle": "Agent", "organizationTitle": "Organization 01", "startDate": "2017-11-15", "endDate": "2017-11-15", "automatic": true, "useDate": "2017-11-15" }, { "userRoleId": 4, "userId": 1, "roleId":4, "organizationId": "ORG_02", "roleTitle": "Referent", "organizationTitle": "Organization 02", "startDate": "2017-11-15", "endDate": "2017-11-15", "automatic": true, "useDate": "2017-11-15" }, { "userRoleId": 5, "userId": 1, "roleId": 2, "organizationId":"ORG_02", "roleTitle": "Agent", "organizationTitle": "Organization 02", "startDate": "2017-11-15", "endDate": "2017-11-15", "automatic": true, "useDate": "2017-11-15" } ];
    
    var result = data.reduce(function(r, o){
      r[o.organizationId] = r[o.organizationId] || {id : o.organizationId, lib : o.organizationTitle, roles : []};
      r[o.organizationId].roles.push({id : o.roleId, title: o.roleTitle});
      return r;
    },{});
    var output = Object.values(result);
    console.log(output);

    【讨论】:

    • 感谢为我节省了很多字节 x-)
    • 很高兴为您提供帮助:)
    【解决方案2】:

    你可以用一个循环来做到这一点:

     const result = [], hash = {};
    
     for(const {roleTitle : role, organizationId : id, organizationTitle : title, userId} of data){
       const key = id+"#"+title;
       if(hash[key]){
         hash[key].roles.push({ id: userId, role });
       } else {
         result.push(hash[key] = {
            id, title, roles : [{ id : userId, role}]
         });
      }
     }
    

    【讨论】:

      【解决方案3】:

      单次迭代的 ES6:

      const newData = data.reduce(
        (obj, { organizationId: id, organizationTitle: lib, roleId, roleTitle }) => {
          obj[id] = obj[id] || { id, lib, roles: [] };
          obj[id].roles.push({ id: roleId, title: roleTitle });
          return obj;
        }, {});
      

      【讨论】:

        猜你喜欢
        • 2023-01-25
        • 2021-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-28
        • 2015-10-19
        相关资源
        最近更新 更多