简单问题的难题:)
说我们有一本书清单 它们属于不同的类别,这些类别是本书中的数组属性
我们希望将这个json转换为一个独特类别列表,其中包含类别
下的书籍首先关闭:json:
[
{
"description":"book 1 description",
"title":"book 1 title",
"id":"4",
"logo":"",
"image":"",
"categories":[
{
"id":"1",
"title":"Logistiek"
},{
"id":"2",
"title":"Finances"
}
]
},
{
"description":"book 2 description",
"title":"book 2 title",
"id":"1",
"logo":"",
"image":"",
"categories":[
{
"id":"3",
"title":"Telecom"
}
]
},
{
"description":"book 3 description",
"title":"book 3 title",
"id":"2",
"logo":"",
"image":"",
"categories":[
{
"id":"3",
"title":"Telecom"
}
]
},
{
"description":"book 4 description",
"title":"book 4 title",
"id":"3",
"logo":"",
"image":"",
"categories":[
{
"id":"2",
"title":"Finances"
}
]
}
]
现在我自己管理的是:
我首先绘制了所有类别:
var data = {} // lets say all json is inhere...
var res = _(data).map(function(m){
return m.categories;
});
这个我分为1个类别(因为现在它是每本书的数组。
res = _(res).flatten();
这给了我一个包含所有类别项目的数组,尽管它有两倍。 现在我还没有比这更进一步。
我尝试在展平之前使用union方法但是没有帮助 我在更大的阵列上尝试了uniq,但我认为我必须将它们分解为单独的数组才能使uniq工作
我很难从这一类别中获取独特的价值。 之后我可以设法在类别
下添加书籍如果有人得到了一些想法,或者告诉我,我这样做完全错了:)请告诉我,如果我可以做得更短或更好的表现,可以通过另一个方向随意扔给我。
UPDATE1
好吧,现在我进一步了,但我很确定它不理想,(太多步骤,我觉得获得一个独特的列表可能会比这些步骤更快)// get all categorie arrays
var res = _(data).map(function(m){
return m.categories;
});
// flatten them
res = _(res).flatten();
// reduce to unique ID array
var catIds = _(res).pluck('id');
catIds = _(catIds).uniq();
// from here on create an array with unique categories
var cats = [];
_(catIds).each(function(cId){
var s = _(res).filter(function(c){
return c.id === cId;
});
cats.push(_(s).first());
});
我可以更快地做到这一点吗?
见jsFiddle在行动...... http://jsfiddle.net/saelfaer/JVxGm/
更新2
好的,我得到了更多,感谢你们下面的帮助, 但我仍然觉得使用2个eaches并不是达到目的的最好方法。var json = [] // lets say the above json is in this variable.
var books = _(json).map(function(book) {
var cats = book.categories;
delete book.categories;
return _(cats).map(function(cat) {
return _({}).extend(book, { category: cat });
});
});
books = _(books).flatten();
var booksPerCategory = [];
_(books).each(function(book){
if(!_(booksPerCategory).any(function(cat){
return cat.id === book.category.id;
}))
{ booksPerCategory.push(book.category); }
});
_(booksPerCategory).each(function(cat){
var mods = _(books).filter(function(book){
return book.category.id === cat.id;
});
cat['modules'] = mods;
});
你可以看到我想要收到的东西:booksByCategory数组 以及我从下面得到的帮助:书籍对象 在这个jsfiddle:http://jsfiddle.net/saelfaer/yWCgt/
答案 0 :(得分:1)
这里有一些帮助,它不能解决你的整个问题,但我认为你应该可以从那里拿走它;)
关键是使用groupBy
。像下面这样的东西应该给你一个良好的开端!
_.groupBy(data, function (book) {
return _.map(book.categories, function (category) {
return category.id;
});
});
答案 1 :(得分:0)
你可以这样做:
var books = _(json).map(function(book) {
var cats = book.categories;
delete book.categories;
return _(cats).map(function(cat) {
return _({}).extend(book, { category: cat.id });
});
});
books = _(books).flatten();
books = _(books).groupBy(function(book) { return book.category });
演示:http://jsfiddle.net/ambiguous/jaL8n/
如果你只想要每一本书的属性片段,那么你可以调整它:
return _({}).extend(book, { category: cat.id });
相应;例如,如果您只想要标题和类别ID:
return _(cats).map(function(cat) {
return {
category: cat.id,
title: book.title
};
});
演示:http://jsfiddle.net/ambiguous/EFLDR/
您不需要显式生成一组唯一的类别ID,您只需要适当地排列数据,并且所有内容都会自行消失(这与功能方法相同)。
更新:根据评论,我认为您只需要在reduce
之后添加flatten
而不是groupBy
:
var books = _(json).map(function(book) {
var cats = book.categories;
delete book.categories;
return _(cats).map(function(category) {
return {
category: category,
book: book
};
});
});
books = _(books).flatten();
books = _(books).reduce(function(h, b) {
if(!h[b.category.id])
h[b.category.id] = _(b.category).extend({ modules: [ ] });
h[b.category.id].modules.push(b.book);
return h;
}, { });
演示:http://jsfiddle.net/ambiguous/vJqTz/
您还可以使用chain
和一些命名函数来使其更易于阅读:
function rearrange(book) {
var cats = book.categories;
delete book.categories;
return _(cats).map(function(category) {
return {
category: category,
book: book
};
});
}
function collect_into(h, b) {
if(!h[b.category.id])
h[b.category.id] = _(b.category).extend({ modules: [ ] });
h[b.category.id].modules.push(b.book);
return h;
}
var books = _.chain(json).
map(rearrange).
flatten().
reduce(collect_into, { }).
value();