Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping Nested Objects with Dynamic Keys (Using Lodash)

I'm querying Firebase to get some data to throw into Chart.js. Here's how I've laid out my data:

{
  "20160428": {
    "follow": 13,
    "host": 6,
    "raid": 1,
    "substreak": 1,
    "tip": 1
  },
  "20160429": {
    "follow": 15,
    "host": 21,
    "raid": 2,
    "substreak": 4
  },
  "20160430": {
    "follow": 4
  },
  "20160501": {
    "follow": 11,
    "host": 15,
    "subscription": 4,
    "substreak": 5
  },
  "20160502": {
    "follow": 2,
    "host": 6,
    "subscription": 1,
    "substreak": 4
  },
  "20160503": {
    "follow": 2
  }
}

As you can see, each object is keyed off by a timestamp and events don't always appear in every object (but there are a finite number of events). Here's how I'd like the data to look so I can feed it into Chart.js:

labels: ["20160428", "20160429", "20160430", ...]

{
  "follow": [13, 15, 4, 11, 2, 2],
  "host": [6, 21, 0, 15, 6, 0],
  "raid": [1, 2, 0, 0, 0, 0],
  "subscription": [0, 0, 0, 4, 1, 0]
  "substreak": [1, 4, 0, 5, 4, 0]
  "tip": [1, 0, 0, 0, 0, 0]
}

I've played with Lodash's groupBy and similar functions, but I'm not sure if I'm on the right track. I wouldn't mind doing this x times either per event, but at this point I can't change the schema.

like image 429
Bryan Veloso Avatar asked Dec 07 '25 07:12

Bryan Veloso


1 Answers

If you have a defined set of keys that you want to group then you have to:

  1. Use map() to pluck values with compact() to get non-null values from the object collection from the defined set of keys.

  2. Build the result using zipObject() from the defined keys and values obtained from the first step.


var keys = ["follow", "host", "raid", "substreak", "tip", "subscription"];
var values = _.map(keys, key => _(data).map(key).compact().value());
var result = _.zipObject(keys, values);

var data = {
  "20160428": { "follow": 13, "host": 6, "raid": 1, "substreak": 1, "tip": 1 },
  "20160429": { "follow": 15, "host": 21, "raid": 2, "substreak": 4 },
  "20160430": { "follow": 4 },
  "20160501": { "follow": 11, "host": 15, "subscription": 4, "substreak": 5 },
  "20160502": { "follow": 2, "host": 6, "subscription": 1, "substreak": 4 },
  "20160503": { "follow": 2 }
};

var keys = ["follow", "host", "raid", "substreak", "tip", "subscription"];
var values = _.map(keys, key => _(data).map(key).compact().value());
var result = _.zipObject(keys, values);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.2/lodash.js"></script>

If you want to group them from all the keys present in the object collection then you can:

  1. Get all the unique keys by:

    • map() each data object inside the object collection
    • flatten() the resulting array
    • Use uniq() to get all unique keys from the flattened array.
  2. Use the methodology in the first example to get the values and build the object.


var keys = _(data).map(_.keys).flatten().uniq().value();
var values = _.map(keys, key => _(data).map(key).compact().value());
var result = _.zipObject(keys, values);

var data = {
  "20160428": { "follow": 13, "host": 6, "raid": 1, "substreak": 1, "tip": 1 },
  "20160429": { "follow": 15, "host": 21, "raid": 2, "substreak": 4 },
  "20160430": { "follow": 4 },
  "20160501": { "follow": 11, "host": 15, "subscription": 4, "substreak": 5 },
  "20160502": { "follow": 2, "host": 6, "subscription": 1, "substreak": 4 },
  "20160503": { "follow": 2 }
};

var keys = _(data).map(_.keys).flatten().uniq().value();
var values = _.map(keys, key => _(data).map(key).compact().value());
var result = _.zipObject(keys, values);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.2/lodash.js"></script>
like image 50
ryeballar Avatar answered Dec 08 '25 20:12

ryeballar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!