2

I have a list of elements with some attributes like

doc.title = 'some title' doc.category = 'book' doc.year = '2016' 

other possible categories can be paper, article, etc.

Now, lets say there are two buttons 'Sort by Category' and 'Sort by Year'.

When 'Sort by Category' is clicked the list should like:

Book 1. book 1 2. book 2 Paper 1. paper 1 2. paper 2 Article 1. article 1 2. article 2 

And when the 'Sort by Year' button is clicked

2016 1. 2. 3. 2015 1. 2. 

and so on.

I want to do this while keeping the size of the html page as small as possible. Please let me know what is the best way to accomplish this.

5
  • 1
    share your list of elements Commented Aug 27, 2016 at 5:55
  • Use a library like Datatables. Commented Aug 27, 2016 at 5:57
  • show your current html code Commented Aug 27, 2016 at 6:00
  • @Barmar Datatables does not have the feature to have category names. Commented Aug 27, 2016 at 6:16
  • It has row grouping: datatables.net/examples/advanced_init/row_grouping.html Commented Aug 27, 2016 at 6:18

1 Answer 1

1

Something like this should get you started - the code is commented with explanations (see it in action):

// convert array of objects into a Map grouped and ordered by supplied key function group(items, key) { // get unique values for grouping key const unique = [ ...new Set(items.map(item => item[key])) ]; // will be ascending by default unique.sort(); // sorting all of the results by title field const sortFn = (a, b) => a.title > b.title; const sortItems = (val) => { // filters the result set to items sharing the current group field value let sorted = items.filter(item => item[key] === val); // sort by title sorted.sort(sortFn); return sorted; } // reduce to a Map (which preserves insertion order and maintains the group key sorting) return unique.reduce((map, cur) => map.set(cur, sortItems(cur)), new Map()); } // testing it out data = [{ title: 'foo', category: 'book', year: 2016, }, { title: 'bar', category: 'book', year: 2016, }, { title: 'blah', category: 'paper', year: 2010, }, { title: 'idk', category: 'paper', year: 2015, }] group(data, 'category'); // Map {"book" => [Object, Object], "paper" => [Object, Object]} group(data, 'year'); // Map {2010 => [Object], 2015 => [Object], 2016 => [Object, Object]} 

For displaying, you can use for...of with destructuring:

for (let [category, items] of group(data, 'category')) { console.log(` <div class="item"> <h3>${category}</h3> <ol>${items.map(item => `<li>${item.title}</li>`).join('')}</ol> </div> `); } 

Note that even though I used ES6 throughout, this can easily be refactored to be more backwards compatible.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.