user1916077
user1916077

Reputation: 451

Typescript/Lodash - Group data in series

I am trying to figure out how to group values in series. For example, I would like to transform the data below

[
    {"book": "Typescript 1", "year": "2015", "units": 1000}, 
    {"book": "Javascript 1", "year": "2015", "units": 2000}, 
    {"book": "Typescript1", "year": "2016", "units": 6000}
]

in

[   
    {
         "book": "Typescript 1",
         "series": [
              {"year": "2015", "units": 1000},
              {"year": "2016", "units": 6000}
         ]
    },   
    {
         "book": "Javascript 1",
         "series": [
              {"year": "2015", "units": 2000}
         ]   
    } 
]

Upvotes: 0

Views: 1308

Answers (3)

jo_va
jo_va

Reputation: 13983

Here is a succinct way to do it with plain JavaScript using reduce() and Object.values():

const books = [
  {"book": "Typescript 1", "year": "2015", "units": 1000}, 
  {"book": "Javascript 1", "year": "2015", "units": 2000}, 
  {"book": "Typescript 1", "year": "2016", "units": 6000}
];

const merged = Object.values(books.reduce((acc, { book, year, units }) => {
  acc[book] = acc[book] || { book, series: [] };
  acc[book].series.push({ year, units });
  return acc;
}, {}));

console.log(merged);

Upvotes: 0

Pawel
Pawel

Reputation: 3802

Please read "Why using _.chain is a mistake." and why flow() is advised.

Here is a fewliner that approaches the problem from functional programming perspective:

import tap from "lodash/fp/tap";
import flow from "lodash/fp/flow";
import groupBy from "lodash/fp/groupBy";

const map = require('lodash/fp/map').convert({ 'cap': false });

const result = flow(
        groupBy('book'),
        map((series, book) => ({book, series: series.map(({units, year}) => 
        ({year, units}) )})),
        tap(console.log)
    )(input)

Where input is an array that you want to convert.

Upvotes: 2

kimy82
kimy82

Reputation: 4495

I will provide an starting point approach without using typescript. If you want more help you should tell us which is your approach.

var original = [
    {"book": "Typescript 1", "year": "2015", "units": 1000}, 
    {"book": "Javascript 1", "year": "2015", "units": 2000}, 
    {"book": "Typescript1", "year": "2016", "units": 6000}
];

const mapBook = new Map();

original.forEach((value) => {
    const year = value['year'];
    const book = value['book'];
    const units = value['units'];

    if(!mapBook.has(book)) {
        const mapYear = new Map();
        mapYear.set(year, units);
        mapBook.set(book, mapYear);
    } else { 
        const mapYear = mapBook.get(book);
        if(mapYear.has(year)){
            //Decide what to do if it is reapeted
        } else {
            mapYear.set(year, units);
            mapBook.set(book, mapYear);
        }
    }
});
const mapBookIterator = mapBook.entries();
for(let [key, value] of mapBookIterator ){
    //iterate your entries and build your object
    console.log(key, value);
}

Upvotes: -1

Related Questions