我有以下
const post = [
{ postTitle: 'Title1', key: 'key1' },
{ postTitle: 'Title2', key: 'key2' }
];
const comment = [
{ key: 'key1', c: 'comment1' },
{ key: 'key1', c: 'comment2' },
{ key: 'key2', c: 'commentA' },
{ key: 'key2', c: 'commentB' },
{ key: 'key2', c: 'commentC' }
];
最后我得到以下结果:
const newPost = [
{
postTitle: 'Title1',
key: 'key1',
comment: ['comment1', 'comment2']
},
{
postTitle: 'Title2',
key: 'key2',
comment: ['commentA', 'commentB', 'commentC']
}
];
以下代码似乎几乎可以完成工作,但是它覆盖了我的注释。我只得到每个postTitle
的最新评论。我该如何修复代码或改进代码以完全像上面的结果一样?
这是有问题的代码:
for (var i = 0; i < post.length; ++i) {
for (var j = 0; j < comment.length; j++) {
if (post[i].key === comment[j].key) {
post[i].comment = [];
post[i].comment.push([comment[j].c]);
} else {
console.log('no comment to add');
}
}
}
此外,如果有更优雅的重构代码,请在此处共享。谢谢。
答案 0 :(得分:1)
问题
正如您所指出的,代码的问题是您覆盖了注释数组。问题出在这里:
post[i].comment = [];
仅当数组不存在时才执行以上行 ,而不是每次执行。
使用简单的条件检查替换上面的行即可:
if (!post[i].comment) post[i].comment = [];
const post = [{postTitle : 'Title1', key: 'key1'},{postTitle : 'Title2', key: 'key2'}];
const comment = [{key : 'key1', c: "comment1"},{key : 'key1', c: "comment2"},{key : 'key2', c: "commentA"},{key : 'key2', c: "commentB"},{key : 'key2', c: "commentC"}];
for (var i = 0; i < post.length; ++i) {
for (var j = 0; j < comment.length; j++) {
if (post[i].key === comment[j].key) {
if (!post[i].comment) post[i].comment = [];
post[i].comment.push([comment[j].c]);
} else {
console.log('no comment to add');
}
}
}
console.log(post);
建议的重构
我将map()
用于外部迭代,将reduce()
用于内部迭代。
内部reduce()
检索相关注释并将它们作为数组返回。外部.map()
将这些注释作为属性添加到post
中(并将修改后的帖子作为新数组返回)。
const post = [{postTitle : 'Title1', key: 'key1'},{postTitle : 'Title2', key: 'key2'}];
const comments = [{key : 'key1', c: "comment1"},{key : 'key1', c: "comment2"},{key : 'key2', c: "commentA"},{key : 'key2', c: "commentB"},{key : 'key2', c: "commentC"}];
const result = post.map(post => {
post.comments = comments.reduce((out,comment) => { //Optimized .filter() + .map()
if (comment.key === post.key) out.push(comment.c);
return out;
}, []);
return post;
});
console.log(result);
为了解决前面的评论,尽管我相信.filter()
+ .map()
会导致代码看起来更简洁,但我选择使用.reduce()
来组合它们。这仅仅是为了提高效率;我更喜欢一个内循环而不是两个。
答案 1 :(得分:1)
稍有不同的方法将注释扫描一次,然后将它们组合在一起,然后使用生成的对象作为映射帖子的查找:
const combine = (posts, comments) => {
const keyedComments = comments .reduce (
(a, {key, c}) => (a [key] = (a [key] || [] ) .concat(c), a),
{}
)
return posts .map ( ({key, ...rest}) => ({
...rest,
comment: keyedComments [key] || []
}))
}
const post = [{postTitle : 'Title1', key: 'key1'}, {postTitle : 'Title2', key: 'key2'}]
const comment = [{key : 'key1', c: "comment1"}, {key : 'key1', c: "comment2"}, {key : 'key2', c: "commentA"}, {key : 'key2', c: "commentB"}, {key : 'key2', c: "commentC"}]
console .log (
combine (post, comment)
)
答案 2 :(得分:0)
您快到了,我在代码中添加了注释,以说明问题所在。
post = [
{postTitle: 'Title1', key: 'key1'},
{postTitle: 'Title2', key: 'key2'}
];
comment = [
{key: 'key1', c: "comment1"},
{key: 'key1', c: "comment2"},
{key: 'key2', c: "commentA"},
{key: 'key2', c: "commentB"},
{key: 'key2', c: "commentC"}
];
for (var i = 0; i < post.length; ++i) {
for (var j = 0; j < comment.length; j++) {
if (post[i].key === comment[j].key) {
// Only set post[i].comment = [] when it is undefined (Only when the first comment is being added)
if (typeof post[i].comment === 'undefined') {
post[i].comment = [];
}
// Push only the comment, instead of [comment[j].c]
post[i].comment.push(comment[j].c);
} else {
console.log('no comment to add');
}
}
}
console.log('post:', post);
console.log('comment:', comment);
另一种方法:
使用Array.find获取与此评论相关的信息,然后我们Array.isArray
检查post.comments
是否已经存在,推送它,否则创建post.comments
键< / p>
posts = [
{postTitle: 'Title1', key: 'key1'},
{postTitle: 'Title2', key: 'key2'}
];
comments = [
{key: 'key1', c: "comment1"},
{key: 'key1', c: "comment2"},
{key: 'key2', c: "commentA"},
{key: 'key2', c: "commentB"},
{key: 'key2', c: "commentC"}
];
result = comments.map((comment) => {
let post = posts.find(o => o.key === comment.key);
Array.isArray(post.comments) ? post.comments.push(comment.c) : post.comments = [comment.c];
});
console.log('posts', posts);
console.log('comments', comments);
答案 3 :(得分:0)
请尝试以下示例
const post = [
{ postTitle: 'Title1', key: 'key1' },
{ postTitle: 'Title2', key: 'key2' }
];
const comment = [
{ key: 'key1', c: 'comment1' },
{ key: 'key1', c: 'comment2' },
{ key: 'key2', c: 'commentA' },
{ key: 'key2', c: 'commentB' },
{ key: 'key2', c: 'commentC' }
];
const newPost = [
{
postTitle: 'Title1',
key: 'key1',
comment: ['comment1', 'comment2']
},
{
postTitle: 'Title2',
key: 'key2',
comment: ['commentA', 'commentB', 'commentC']
}
];
const result = post.map(p => {
const obj = Object.assign({}, p);
obj.comment = comment.filter(c => c.key === p.key).map(c => c.c);
return obj;
});
console.log(result);
答案 4 :(得分:0)
之所以只得到每个postTitle
的最后一条评论,是因为该if语句
if (post[i].key === comment[j].key) {
// each time the post[i].key === comment[j].key
// the line below is resetting the post[i].comment array to an
// empty array
post[i].comment = [];
post[i].comment.push([comment[j].c]);
}
您应该改写
for (var i = 0; i < post.length; ++i) {
for (var j = 0; j < comment.length; j++) {
if (post[i].key === comment[j].key) {
// line below will check if there isn't a post[i].comment array
// declared yet
if (!post[i].comment){
post[i].comment = [];
}
post[i].comment.push(comment[j].c);
}
else {
console.log('no comment to add'); }
}
}
希望这会有所帮助。