2012-03-15 14 views
1

一個簡單的問題:)underscorejs:如何從合併的性能獨特的類對象的數組上

說我們的書 列表,它們是在不同類別困難的題目,這些類別的數組屬性書上

我們想要的類別

第一關下改變這個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(); 

這給了我一個所有類別項的數組,雖然這有雙打。 現在我還沒有比這更進一步。

我嘗試使用工會法壓扁之前,但沒有幫助了 我想更大的陣列上的uniq,但我想我已經打破時間下來到單獨的陣列來uniq的工作

我是堅持從該類別數組中獲得唯一值。 之後,我可以設法添加類別下的書籍

如果有人有一些想法,通過轉向另一個方向可以讓我更好地表現自己。

UPDATE1

OK,現在我有一個小進一步,但我敢肯定它的效果並不理想,(步驟太多,我得到一個感覺,得到一個獨特的名單可以比這些步驟去更快)

// 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

你可以做這樣的事情:

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,你只需要適當地安排你的數據並且一切都會自行消失(如同功能方法一樣)。


UPDATE:根據意見,我想你只需要flatten代替後添加reduce一個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(); 

演示:http://jsfiddle.net/ambiguous/kSU7v/

+0

嘿,感謝所有幫助,因爲它不是100%所期望的結果,(我忘了指定),我與你的jsfiddle的叉子撥弄周圍,你可以看到我想要得到http://jsfiddle.net/saelfaer/yWCgt/,正如你所看到的,也許我對下劃線庫的有限瞭解使得我再次抓住每一個來做某些事情,而且是的,我倒退了抽出一個獨特的再次陣列,因爲我需要的不僅僅是id上的一個groupby,我需要整個類別obj,不要猶豫,儘管指向我的捷徑或更好的解決方案。再次感謝! – Sander 2012-03-16 09:53:52

+0

@桑德:看看我的更新,我想我知道你現在在做什麼。 – 2012-03-16 19:15:15

1

這裏有一些幫助,但它確實沒有解決你的整個問題,但我認爲你應該能夠從那裏取得;)

關鍵是在使用groupBy。像下面的東西應該給你一個好的開始!

_.groupBy(data, function (book) { 
    return _.map(book.categories, function (category) { 
    return category.id; 
    }); 
}); 
相關問題