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.
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.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments