我正在使用TypeScript作为Web应用程序的后端,我发现交集类型对于进行高效的SQL查询非常有用。基本上,如果我有以下表格:
User
userId: number
userEmail: string
Post
postId: number
userId: number (FK)
postBody: string
我最终会得到一个如下所示的交叉类型(User& Post):
{
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
函数似乎无法判断子对象是否相等,在这个例子中它仍然给出了一个包含三个对象的数组。
答案 0 :(得分:0)
如何尝试下面的内容,进入循环并创建对象
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);
答案 1 :(得分:0)
您可以使用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));
&#13;
答案 2 :(得分:0)
这是另一种减少,一些和解构的方法
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));