Skip to content

Instantly share code, notes, and snippets.

@mfellner
Created April 6, 2017 17:08
Show Gist options
  • Save mfellner/16dcf7a37497824be85a97290813b5c3 to your computer and use it in GitHub Desktop.
Save mfellner/16dcf7a37497824be85a97290813b5c3 to your computer and use it in GitHub Desktop.
Playing around with combinations of generators.
'use strict';
const items = [
{ id: 'a', group: 'x', count: 20 },
{ id: 'b', group: 'x', count: 10 },
{ id: 'c', group: 'x', count: 40 },
{ id: 'c', group: 'y', count: 40 },
{ id: 'c', group: 'y', count: 10 },
{ id: 'c', group: 'y', count: 30 },
{ id: 'c', group: 'z', count: 20 },
{ id: 'c', group: 'z', count: 30 }
];
function groupBy(key) {
return items =>
items.reduce(
(grouped, item) => {
const value = item[key];
if (value in grouped) {
grouped[value].push(item);
} else {
grouped[value] = [item];
}
return grouped;
},
{}
);
}
function groupGenerator(key) {
const groupFn = groupBy(key);
return function*(items, i = 0) {
const groups = groupFn(items);
const keys = Object.keys(groups).sort();
for (let k = 0; k < keys.length; k += 1) {
const key = keys[(k + i) % keys.length];
yield groups[key];
}
};
}
function sortBy(key) {
return items => items.slice().sort((a, b) => {
if (a[key] < b[key]) {
return -1;
}
if (a[key] > b[key]) {
return 1;
}
return 0;
});
}
function sortGenerator(key) {
const sortFn = sortBy(key);
return function*(items) {
const sorted = sortFn(items);
for (let i of sorted) {
yield i;
}
};
}
function groupedSortedGenerator(groupKey, sortKey) {
const group = groupGenerator(groupKey);
const sort = sortGenerator(sortKey);
return function*(items) {
for (let g of group(items)) {
for (let i of sort(g)) {
yield i;
}
}
};
}
function interleavedGenerator(groupKey, sortKey) {
const group = groupGenerator(groupKey);
const sort = sortGenerator(sortKey);
return function*(items) {
const groups = Array.from(group(items));
const iterators = groups.map(g => sort(g)[Symbol.iterator]());
for (let i = 0; i < items.length; ) {
const it = iterators[i % iterators.length];
const next = it.next();
if (!next.done) {
i += 1;
yield next.value;
} else {
continue;
}
}
};
}
const groupedSorted = Array.from(groupedSortedGenerator('group', 'count')(items));
const interleaved = Array.from(interleavedGenerator('group', 'count')(items));
console.log('Grouped-sorted:');
console.log(groupedSorted);
console.log('Interleaved:');
console.log(interleaved);
// Grouped-sorted:
// [ { id: 'b', group: 'x', count: 10 },
// { id: 'a', group: 'x', count: 20 },
// { id: 'c', group: 'x', count: 40 },
// { id: 'c', group: 'y', count: 10 },
// { id: 'c', group: 'y', count: 30 },
// { id: 'c', group: 'y', count: 40 },
// { id: 'c', group: 'z', count: 20 },
// { id: 'c', group: 'z', count: 30 } ]
// Interleaved:
// [ { id: 'b', group: 'x', count: 10 },
// { id: 'c', group: 'y', count: 10 },
// { id: 'c', group: 'z', count: 20 },
// { id: 'a', group: 'x', count: 20 },
// { id: 'c', group: 'y', count: 30 },
// { id: 'c', group: 'z', count: 30 },
// { id: 'c', group: 'x', count: 40 },
// { id: 'c', group: 'y', count: 40 } ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment