ค้นหาเว็บไซต์

javascript - ฉันจะจัดกลุ่มอาร์เรย์ของอ็อบเจ็กต์ตามซับอ็อบเจ็กต์ได้อย่างไร?


ฉันกำลังใช้ TypeScript สำหรับส่วนหลังของเว็บแอป และฉันพบว่าประเภท intersection มีประโยชน์มากสำหรับการสร้างคำสั่ง SQL ที่มีประสิทธิภาพ โดยพื้นฐานแล้ว ถ้าฉันมีตารางดังต่อไปนี้:

User

userId: number
userEmail: string

Post

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

ฉันอาจจบลงด้วยประเภทการตัดกัน (User & Post) ที่มีลักษณะดังนี้:

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

ซึ่งหมายความว่าฉันสามารถใช้ประเภทนี้เพื่อแทนแถวที่ฉันได้รับกลับมาจากการสืบค้นแบบ join select

ปัญหาคือว่าฉันต้องแยกข้อมูลในเว็บเซิร์ฟเวอร์ หลังจากนั้นฉันต้องเขียนโค้ดซ้ำเพื่อนำมาจัดกลุ่มสำหรับทุกคำค้นหา และนี่อาจทำให้เกิดความซ้ำซ้อน นี่คือลักษณะของการแปลงที่ฉันพยายามทำ:

ใน :

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

ออก :

[
  {
    userId: 1,
    userEmail: '[email ',
    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 ของมันดูเหมือนไม่สามารถบอกได้ว่าวัตถุย่อยเท่ากันและมันก็ยังให้ฉันเป็นอาร์เรย์ของสามวัตถุในตัวอย่างนี้อยู่ดี

คำตอบ #1

ลองทำอะไรประมาณด้านล่างนี้ โดยวนลูปและสร้างอ็อบเจ็กต์

var arry = [
    {
        userId: 1,
        userEmail: '[email ',
        postId: 1,
        postBody: 'User 1\'s first post',
    },
    {
        userId: 1,
        userEmail: '[email ',
        postId: 2,
        postBody: 'User 1\'s second post',
    },
    {
        userId: 2,
        userEmail: '[email ',
        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: '[email ',
        postId: 1,
        postBody: 'User 1\'s first post',
    },
    {
        userId: 1,
        userEmail: '[email ',
        postId: 2,
        postBody: 'User 1\'s second post',
    },
    {
        userId: 2,
        userEmail: '[email ',
        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));