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));