【问题标题】:How do I group an array of objects by subobject?如何按子对象对对象数组进行分组?
【发布时间】:2018-05-01 23:43:06
【问题描述】:

我将 TypeScript 用于 Web 应用程序的后端,我发现交集类型对于进行高效的 SQL 查询非常有用。基本上,如果我有以下表格:

User

userId: number
userEmail: string

Post

postId: number
userId: number (FK)
postBody: string

我可以得到如下所示的交集类型(用户和帖子):

{
  userId: number;
  userEmail: string;
  postId: number;
  postBody: string;
}

这意味着我可以使用这种类型来表示我从连接的选择查询中返回的行。

问题是我必须在 Web 服务器中分离数据。我必须编写迭代代码来为每个查询对它们进行分组,这可能会重复。这是我想要实现的转变:

在:

[
  {
    userId: 1,
    userEmail: 'user1@email.com',
    postId: 1,
    postBody: 'User 1\'s first post',
  },
  {
    userId: 1,
    userEmail: 'user1@email.com',
    postId: 2,
    postBody: 'User 1\'s second post',
  },
  {
    userId: 2,
    userEmail: 'user2@email.com',
    postId: 3,
    postBody: 'User 2\'s first post',
  },
]

输出:

[
  {
    userId: 1,
    userEmail: 'user1@email.com',
    posts: [
      {
        postId: 1,
        postBody: 'User 1\'s first post',
      },
      {
        postId: 2,
        postBody: 'User 1\'s second post',
      }
    ],
  },
  {
    userId: 2,
    userEmail: 'User 2\'s email',
    posts: [
      {
        postId: 3,
        postBody: 'User 2\'s first post',
      }
    ]
  }
]

我正在尝试提出一个可以用来动态执行此操作的函数,可能会传入集合、父键名称数组和子集合的名称。我最终得到了一个不成功的函数,签名如下:function group(coll: Array<any>, parentKeys: Array<string>, childCollName: string): Array<any>;

我想知道是否有人可以帮助我实现这一点。

到目前为止,我已经尝试过使用 Lodash。但是,它的groupBy 函数似乎无法判断子对象是否相等,并且在此示例中它仍然为我提供了一个包含三个对象的数组。

【问题讨论】:

    标签: javascript arrays typescript grouping


    【解决方案1】:

    试试下面的方法,进入循环并创建对象

    var arry = [
        {
            userId: 1,
            userEmail: 'user1@email.com',
            postId: 1,
            postBody: 'User 1\'s first post',
        },
        {
            userId: 1,
            userEmail: 'user1@email.com',
            postId: 2,
            postBody: 'User 1\'s second post',
        },
        {
            userId: 2,
            userEmail: 'user2@email.com',
            postId: 3,
            postBody: 'User 2\'s first post',
        },
    ];
    
    function createPost(obj) {
        post = {};
        post.postId = obj.postId;
        post.postBody = obj.postBody;
        return post;
    }
    function convert(array) {
        var map = {};
        for (var i = 0; i < array.length; i++) {
            var currentObject = array[i];
    
    
            if (!map[currentObject.userId]) {
                obj = {}
                obj.userId = currentObject.userId;
                obj.userEmail = currentObject.userEmail;
                obj.posts = [];
    
                map[obj.userId] = obj;
    
            }
            obj.posts.push(createPost(currentObject));
        }
        var keys = Object.keys(map);
        return keys.map(function (v) { return map[v]; });
    }
    var r = convert(arry)
    console.log(r);

    【讨论】:

      【解决方案2】:

      您可以使用Array.prototype.reduce() 来实现目标。

      var source =
          [
          {
              userId: 1,
              userEmail: 'user1@email.com',
              postId: 1,
              postBody: 'User 1\'s first post',
          },
          {
              userId: 1,
              userEmail: 'user1@email.com',
              postId: 2,
              postBody: 'User 1\'s second post',
          },
          {
              userId: 2,
              userEmail: 'user2@email.com',
              postId: 3,
              postBody: 'User 2\'s first post',
          },
      
      
      ]
      
      
      var grouped = source.reduce(function(v,k){
          if (!v[k.userId]) {
              v[k.userId]={};
          }
          var group = v[k.userId];
          group.userId=k.userId;
          group.userEmail=k.userEmail;
          if(!group.posts){
              group.posts=[];
          }
          group.posts.push({postId: k.postId,
              postBody:k.postBody})
          return v;
      },{})
      
      var dataArray = [];
      for(var o in grouped) {
          if (grouped.hasOwnProperty(o)) {
              dataArray.push(grouped[o]);
          }
      }
      
      console.log(JSON.stringify(dataArray,null, 2));

      【讨论】:

        【解决方案3】:

        这是另一个关于 reduce、some 和 destructuring 的观点

        DEMO

        const grouped = [
          {
            userId: 1,
            userEmail: 'user1@email.com',
            postId: 1,
            postBody: 'User 1\'s first post',
          },
          {
            userId: 1,
            userEmail: 'user1@email.com',
            postId: 2,
            postBody: 'User 1\'s second post',
          },
          {
            userId: 2,
            userEmail: 'user2@email.com',
            postId: 3,
            postBody: 'User 2\'s first post',
          }
        ];
        
        const sorted = grouped.reduce((acc, nxt) => {
            const { userId, userEmail, ...rest } = nxt;
            let index;
            let user;
        
            const accHasUser = acc.some((obj, i) => {
                if (obj && obj.userId === userId) {
                    index = i;
                    return true;
                }
                return false;
            });
        
            if (!accHasUser) {
                user = { userId, userEmail, posts: [rest] };
                acc.push(user);
            } else {
                acc[index].posts.push(rest);
            }
        
            return acc;
        }, []);
        
        console.log(JSON.stringify(sorted));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-11-25
          • 1970-01-01
          • 2014-11-28
          • 2022-01-08
          相关资源
          最近更新 更多