score:1

Accepted answer

I was intrigued by this problem and came up with a first version. It's a little different than yours but here it is. I will note that I didn't try to sort the dates or rename the items to something useful but those can be added.

var data = [
	{date: '9-2-17', item: 1, cost: 100},
  {date: '9-2-17', item: 3, cost: 200},
  {date: '9-4-17', item: 1, cost: 150},
  /* '9-4-17' does not have an entry for item 3 so cost should be counted as null */
  {date: '10-2-17', item: 1, cost: 10},
  {date: '10-2-17', item: 3, cost: 20},
  {date: '10-3-17', item: 2, cost: 2000}
]

// utility functions
const product = (...sets) =>
  sets.reduce((acc, set) =>
    _.flatten(acc.map(x => set.map(y => [ ...x, y ]))),
    [[]]);

// the meat and potatoes
const builder = lookup => pairs => pairs.reduce((agg, [item, date]) => {
   const out = _.cloneDeep(agg);
   const value = _.get(lookup, [date, item, 'cost'], null);
   const evalue = _.get(out, date, []);
   evalue.push(value);
   _.set(out, date, evalue);
   return out;
}, {})

// setup data structures for searching
const byDateByItem = _.mapValues(_.groupBy(data, 'date'), x => _.keyBy(x, 'item'));    
const items = _.uniq(data.map(x=>x.item));
const dates = _.uniq(data.map(x=>x.date));

// create all posibilities
const pairs = product(items, dates);
// populate possibilities with values
const hash = builder(byDateByItem)(pairs);
// put keys with values in their respective lists
const p = _.toPairs(hash).map(_.flatten);
// smash data into a matrix type thing
const table = [['x',...items], ...p];
// flip the table on it's side (╯°□°)╯︵ ┻━┻
const out = _.zip(...table);
console.log('out', out);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


Related Query

More Query from same tag