让我假装一个api正在返回apiResult
中的结构,我想创建一个两级索引来查找给定作者对给定文章的评论。
自己的作者,文章和评论的查找表很容易,但我很难对CommentsByArticleAndAuthor
- 查找。
在mapped
结构中,我展示了如何为三个简单的'做出查找索引。部分,以及我希望CommentsByArticleAndAuthor
看起来的方式。
如何继续生成此索引?
var apiResult = {
Authors: [
{
Id: "author-id-1",
Name: "Author One"
},
{
Id: "author-id-2",
Name: "Author Two"
}
],
Articles: [
{
Id: "article-id-1",
Title: "This Great Article"
}
],
Comments: [
{
Id: "comment-id-1",
AuthorId: "author-id-1",
ArticleId: "article-id-1",
Comment: "that great, hu?"
},
{
Id: "comment-id-2",
AuthorId: "author-id-2",
ArticleId: "article-id-1",
Comment: "yes, that great"
}
]
}
var mapped = {
Authors: _.keyBy(apiResult.Authors, 'Id'),
Articles: _.keyBy(apiResult.Articles, 'Id'),
Comments: _.keyBy(apiResult.Comments, 'Id'),
CommentsByArticleAndAuthor: {
"article-id-1": {
"author-id-1": [ "comment-id-1" ],
"author-id-2": [ "comment-id-2" ]
}
}
}
console.log(JSON.stringify(mapped, null, 2));

<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
&#13;
答案 0 :(得分:1)
您可以迭代注释并构建分层对象结构。
var apiResult = { Authors: [{ Id: "author-id-1", Name: "Author One" }, { Id: "author-id-2", Name: "Author Two" }], Articles: [{ Id: "article-id-1", Title: "This Great Article" }], Comments: [{ Id: "comment-id-1", AuthorId: "author-id-1", ArticleId: "article-id-1", Comment: "that great, hu?" }, { Id: "comment-id-2", AuthorId: "author-id-2", ArticleId: "article-id-1", Comment: "yes, that great" }] },
mapped = { CommentsByArticleAndAuthor: {} };
apiResult.Comments.forEach(function (o) {
var ref = mapped.CommentsByArticleAndAuthor;
ref[o.ArticleId] = ref[o.ArticleId] || {};
ref[o.ArticleId][o.AuthorId] = ref[o.ArticleId][o.AuthorId] || [];
ref[o.ArticleId][o.AuthorId].push(o.Id);
});
console.log(mapped);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
对于更动态的方法,您可以使用数组作为层次结构,使用对象作为默认值。
var apiResult = { Authors: [{ Id: "author-id-1", Name: "Author One" }, { Id: "author-id-2", Name: "Author Two" }], Articles: [{ Id: "article-id-1", Title: "This Great Article" }], Comments: [{ Id: "comment-id-1", AuthorId: "author-id-1", ArticleId: "article-id-1", Comment: "that great, hu?" }, { Id: "comment-id-2", AuthorId: "author-id-2", ArticleId: "article-id-1", Comment: "yes, that great" }] },
mapped = { CommentsByArticleAndAuthor: {} };
apiResult.Comments.forEach(function (o) {
['ArticleId', 'AuthorId'].reduce(function (r, k) {
return r[o[k]] = r[o[k]] || { AuthorId: [] }[k] || {};
}, mapped.CommentsByArticleAndAuthor).push(o.Id);
});
console.log(mapped);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
答案 1 :(得分:1)
您可以将apiResult.Comments
缩减为所需的结果:
CommentsByArticleAndAuthor: apiResult.Comments.reduce((result, comment) => Object.assign(result, {
[comment.ArticleId]: Object.assign(result[comment.ArticleId] || {}, {
[comment.AuthorId]: result[comment.ArticleId] && result[comment.ArticleId][comment.AuthorId]
? result[comment.ArticleId][comment.AuthorId].push(comment.Id)
: [comment.Id]
})
}), {})
你的例子:
var apiResult = {
Authors: [
{
Id: "author-id-1",
Name: "Author One"
},
{
Id: "author-id-2",
Name: "Author Two"
}
],
Articles: [
{
Id: "article-id-1",
Title: "This Great Article"
}
],
Comments: [
{
Id: "comment-id-1",
AuthorId: "author-id-1",
ArticleId: "article-id-1",
Comment: "that great, hu?"
},
{
Id: "comment-id-2",
AuthorId: "author-id-2",
ArticleId: "article-id-1",
Comment: "yes, that great"
}
]
}
var mapped = {
CommentsByArticleAndAuthor: {
"article-id-1": {
"author-id-1": [ "comment-id-1" ],
"author-id-2": [ "comment-id-2" ]
}
},
CommentsByArticleAndAuthor: apiResult.Comments.reduce((result, comment) => Object.assign(result, {
[comment.ArticleId]: Object.assign(result[comment.ArticleId] || {}, {
[comment.AuthorId]: result[comment.ArticleId] && result[comment.ArticleId][comment.AuthorId]
? result[comment.ArticleId][comment.AuthorId].push(comment.Id)
: [comment.Id]
})
}), {})
}
console.log(mapped);
&#13;
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
&#13;
答案 2 :(得分:0)
感谢Ninas great answer我想出了这个通用的解决方案:
const apiResult = {
Authors: [{ Id: "author-id-1", Name: "Author One" },
{ Id: "author-id-2", Name: "Author Two" }],
Articles: [{ Id: "article-id-1", Title: "This Great Article" }],
Comments: [{ Id: "comment-id-1", AuthorId: "author-id-1", ArticleId: "article-id-1", Comment: "that great, hu?" },
{ Id: "comment-id-2", AuthorId: "author-id-2", ArticleId: "article-id-1", Comment: "yes, that great" }]
};
const mapped = {};
const indexBy = function(collection, keys, map = (item) => item) {
let result = {};
collection.forEach((item) => {
keys.reduce((r, k, idx) => {
let value = _.get(item, k);
if (idx === keys.length - 1)
return r[value] = [...r[value] || [], map(item)];
return r[value] = r[value] || {}
}, result);
});
return result;
}
mapped.CommentsByArticlesAndAuthor = indexBy(apiResult.Comments, ['ArticleId', 'AuthorId'], (item) => item.Id);
mapped.CommentsByAuthorAndArticle = indexBy(apiResult.Comments, ['AuthorId', 'ArticleId'], (item) => item.Id);
console.log(mapped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
它允许我索引我想要的多个级别,并且它允许我将索引的项目转换为默认,只是存储完整项目。它还利用来自lodash的get
来支持嵌套的键值,例如: Author.Id
代替AuthorId
。