SourceMap

SourceMap

Simple class that extends Map - to include a source and toString fixes.

Specifically generated from group.by(collection, ...)

Constructor

new SourceMap()

Members

source :String

The property the map was sourced from

Type:
  • String

Methods

getSource() → {String}

Getter for the source

Returns:
Type
String

map(mapFn) → {SourceMap}

Maps a collection within the sourceMap by a function.

Note that this only maps the leaf collection of values, not the intermediary levels.

This can be useful from everything from:

  • sorting the leaf collections,
  • filtering the results to only those that meet certain criteria,
  • to an alternative form of reducing the values,
  • or even combinations of the three or more:
Example
const data = [
weather = [
  { id: 1, city: 'Seattle',  month: 'Aug', precip: 0.87, dateTime: new Date(2020, 7, 1)  , year: 2020},
  { id: 2, city: 'Seattle',  month: 'Dec', precip: 5.31, dateTime: new Date(2020, 11, 1) , year: 2020},
  { id: 0, city: 'Seattle',  month: 'Apr', precip: 2.68, dateTime: new Date(2021, 3, 1)  , year: 2021},
  { id: 4, city: 'New York', month: 'Aug', precip: 4.13, dateTime: new Date(2020, 7, 1)  , year: 2020},
  { id: 5, city: 'New York', month: 'Dec', precip: 3.58, dateTime: new Date(2020, 11, 1) , year: 2020},
  { id: 3, city: 'New York', month: 'Apr', precip: 3.94, dateTime: new Date(2021, 3, 1)  , year: 2021},
  { id: 7, city: 'Chicago',  month: 'Aug', precip: 3.98, dateTime: new Date(2020, 7, 1)  , year: 2020},
  { id: 8, city: 'Chicago',  month: 'Dec', precip: 2.56, dateTime: new Date(2020, 11, 1) , year: 2020},
  { id: 6, city: 'Chicago',  month: 'Apr', precip: 3.62, dateTime: new Date(2021, 3, 1)  , year: 2021}
];

utils.group.by(weather, 'city')
  .map(collection => collection.length);

// SourceMap(3) [Map] {
//   'Seattle' => 3,
//   'New York' => 3,
//   'Chicago' => 3,
//   source: 'city'
// }

utils.group.by(weather, 'city')
    .map(collection => collection.filter(r => r.year === 2020))
    .map(collection => collection.length);

// SourceMap(3) [Map] {
//   'Seattle' => 2,
//   'New York' => 2,
//   'Chicago' => 2,
//   source: 'city'
// }
Parameters:
Name Type Description
mapFn function

{(array) => any} Function to apply to the leaf collections (arrays)

Properties
Name Type Description
collection Array

the collection of records in the group

collectionProps Object

the properties and values the collection was grouped by

Returns:
  • New SourceMap with the leaf collections updated to the results from mapFn
Type
SourceMap

reduce(reduceFn) → {Array}

See:

Reduces a SourceMap by groups, to a collection of objects that can be printed.

Note that the ReduceFn is called at the grouped collection of records level, not the entire collection.

This can be very helpful when working with tables.

new utils.TableGenerator(
  utils.group.by(weather, 'city')
    .reduce((group) => ({
      min: utils.agg.min(group, 'precip'),
      max: utils.agg.max(group, 'precip'),
      avg: utils.agg.avgMean(group, 'precip')
    }))
)
  .render()

Screenshot of reduce with table

Example
collection = [
  { id: 1, city: 'Seattle',  month: 'Aug', precip: 0.87 },
  { id: 0, city: 'Seattle',  month: 'Apr', precip: 2.68 },
  { id: 3, city: 'New York', month: 'Apr', precip: 3.94 },
  { id: 4, city: 'New York', month: 'Aug', precip: 4.13 }
];
utils.group.by(collection, 'city')
   .reduce((records) => {
     min: utils.aggregate.min('precip'),
     max: utils.aggregate.min('precip'),
     avg: utils.aggregate.avgMean('precip')
   });
//-- results
[{ city: 'Seattle', min: 0.87, max: 2.68, avg: 1.78 },
 { city: 'New York', min: 3.94, max: 4.13, avg: 4.06 }];
Parameters:
Name Type Description
reduceFn function

(collection, props) => {Object} - Function that reduces the collection to an object

Properties
Name Type Description
collection Array

the collection of records in the group

collectionProps Object

the properties and values the collection was grouped by

Returns:
  • Array of objects merged with the parent group attributes and reduceFn result
Type
Array

reduceSeparate(reduceFn) → {Array}

See:
  • reduce() - for a compact object with multiple aggregate values, useful for tables

Reduces, but puts each aggregate value on a separate record.

This is particularly useful for charting vega, as series must be on separate objects.

Each object then made per group leaf collection, preserving the groups used to make it.

The object generated by the function is then merged.

utils.vega.svg((vl) => vl.markLine()
    .data(
        utils.group.by(weather, 'city')
            .reduceSeparate((group) => ({
                min: utils.agg.min(group, 'precip'),
                max: utils.agg.max(group, 'precip'),
                avg: utils.agg.avgMean(group, 'precip')
            }))
    )
    .width(200)
    .encode(
        vl.x().fieldN('city'),
        vl.y().fieldQ('_aggregateValue'),
        vl.color().fieldN('_aggregateKey')
));

Screenshot of reduce with chart

Example
utils.group.by(weather, 'city')
  .reduceSeparate((group) => ({
    min: utils.agg.min(group, 'precip'),
    max: utils.agg.max(group, 'precip'),
    avg: utils.agg.avgMean(group, 'precip')
  }));

//-- results
[
  { city: 'Seattle', _aggregateKey: 'min', _aggregateValue: 0.87 },
  { city: 'Seattle', _aggregateKey: 'max', _aggregateValue: 5.31 },
  { city: 'Seattle', _aggregateKey: 'avg', _aggregateValue: 2.953 },
  { city: 'New York', _aggregateKey: 'min', _aggregateValue: 3.58 },
  { city: 'New York', _aggregateKey: 'max', _aggregateValue: 4.13 },
  { city: 'New York', _aggregateKey: 'avg', _aggregateValue: 3.883 },
  { city: 'Chicago', _aggregateKey: 'min', _aggregateValue: 2.56 },
  { city: 'Chicago', _aggregateKey: 'max', _aggregateValue: 3.98 },
  { city: 'Chicago', _aggregateKey: 'avg', _aggregateValue: 3.387 }
]
Parameters:
Name Type Description
reduceFn function

(collection, props) => {Object} - Function that reduces the collection to an object

Properties
Name Type Description
collection Array

the collection of records in the group

collectionProps Object

the properties and values the collection was grouped by

Returns:
Type
Array

setSource(source)

Specify the source

Parameters:
Name Type Description
source Strinng

toJSON() → {Object}

toJSON() override.

Now you can use JSON.stringify(sourceMapInstance) and it will work correctly

or within Jupyter / iJavaScript:

$$.json(sourceMapInstance)

and you can explore the values in collapsing folders

Screenshot using $$.json

Returns:
Type
Object

toString() → {String}

toString() override to use the stringify reducer.

Now you can use String(sourceMapInstance) and it will work correctly.

//-- for instance
String(sourceMapInstance)

provides

{"dataType":"SourceMap","source":"city","data":
[["Seattle",{"dataType":"SourceMap","source":"month","data":
[["Aug",[{"id":1,"city":"Seattle","month":"Aug","precip":0.87}]],
["Apr",[{"id":0,"city":"Seattle","month":"Apr","precip":2.68}]],
["Dec",[{"id":2,"city":"Seattle","month":"Dec","precip":5.31}]]]}],
["New York",{"dataType":"SourceMap","source":"month","data":
[["Apr",[{"id":3,"city":"New York","month":"Apr","precip":3.94}]],
["Aug",[{"id":4,"city":"New York","month":"Aug","precip":4.13}]],
["Dec",[{"id":5,"city":"New York","month":"Dec","precip":3.58}]]]}],
["Chicago",{"dataType":"SourceMap","source":"month","data":
[["Apr",[{"id":6,"city":"Chicago","month":"Apr","precip":3.62}]],
["Dec",[{"id":8,"city":"Chicago","month":"Dec","precip":2.56}]],
["Aug",[{"id":7,"city":"Chicago","month":"Aug","precip":3.98}]]]}]]}
Returns:
Type
String

(static) stringifyReducer(key, value) → {Object}

Use this for a reducer for Maps if ever needed.

(NOTE: SourceMap already uses this where needed, you only would use this for normal maps)

JSON.stringify(new Map()) doesn't work well, it just returns Map()

  • regardless of what it contains

instead use something like this:

//-- can be a map, or any object, even one including a map
const toBeStringified = { value: 'a', map: new Map() };

//-- simple destructure to make it easier to access
const stringifyReducer = utils.SourceMap.stringifyReducer;

//-- pass it in as the second argument
JSON.stringify(toBeStringified, stringifyReducer);

// returns
{"value":"a","map":{"dataType":"Map","value":[["A",1],["B",2]]}}

//-- or on a traditional map
const standardMap = new Map([['a', 1], ['b', 2]]);

JSON.stringify(standardMap, stringifyReducer);

// returns
{"dataType":"Map","value":[["a",1],["b",2]]}
Parameters:
Name Type Description
key String

the name of the property

value any
Returns:
Type
Object