使用动态键对嵌套对象进行分组(使用 Lodash)

Grouping Nested Objects with Dynamic Keys (Using Lodash)

我正在查询 Firebase 以获取一些数据以放入 Chart.js。这是我布置数据的方式:

{
  "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
  }
}

如您所见,每个对象都由时间戳锁定,并且事件并不总是出现在每个对象中(但事件的数量是有限的)。这是我希望数据的外观,以便我可以将其输入 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]
}

我玩过 Lodash 的 groupBy 和类似的功能,但我不确定我是否在正确的轨道上。我不介意每个事件都这样做 x 次,但此时我无法更改架构。

您可以使用普通 javascript 和一些循环。

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 } },
    grouped = {}

Object.keys(data).forEach(function (k) {
    ["follow", "host", "raid", "substreak", "tip"].forEach(function (kk) {
        grouped[kk] = grouped[kk] || [];
        grouped[kk].push(data[k][kk] || 0);
    });
});

document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');

不要在家里尝试这个。

var fields = {
  follow: 0,
  host: 0,
  raid: 0,
  substreak: 0,
  tip: 0,
  subscription: 0
};

_(data)
  .values()
  .map(x => _.assign({}, fields, x))
  .map(_.toPairs)
  .flatten()
  .groupBy(0)
  .mapValues(x => _.map(x, 1))
  .value();

如果您有一组已定义的要分组的键,那么您必须:

  1. 使用map() to pluck values with compact()从定义的键集的对象集合中获取非空值。

  2. 使用 zipObject() 从第一步获得的定义键和值构建结果。


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>

如果您想根据对象集合中存在的所有键对它们进行分组,那么您可以:

  1. 通过以下方式获取所有唯一键:

    • map()对象集合里面的每个数据对象
    • flatten() 结果数组
    • 使用 uniq() 从展平数组中获取所有唯一键。
  2. 使用第一个示例中的方法获取值并构建对象。


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>