从分组的数组对象中创建地图

Create a map out of a grouped array objects

我正在使用 Underscore.js 从现有对象数组映射新对象数组,但无法真正获得所需结果。

基本上我有一个像这样的对象数组:

[
  {
    "total": 5.21,
    "number": 3,
    "a": "Paid",
    "y": 2015,
    "m": 1,
    "d": "2015-01-17T23:58:34.115Z"
  },
  {
    "total": 374.65,
    "number": 3,
    "a": "Scheduled",
    "y": 2015,
    "m": 1,
    "d": "2015-01-18T02:16:03.503Z"
  },
  {
    "total": 310.84,
    "number": 1,
    "a": "Paid",
    "y": 2015,
    "m": 1,
    "d": "2015-01-17T23:58:34.115Z"
  },
  {
    "total": 284.41,
    "number": 3,
    "a": "Scheduled",
    "y": 2015,
    "m": 1,
    "d": "2015-01-18T02:16:03.503Z"
  }
]

我想将其映射为:

[
  {
    "key": "Paid",
    "values": [
      [
        "2015-01-17T23:58:34.115Z",
        5.21
      ],
      [
        "2015-01-17T23:58:34.115Z",
        310.84
      ]
    ]
  },
  {
    "key": "Scheduled",
    "values": [
      [
        "2015-01-18T02:16:03.503Z",
        374.65
      ],
      [
        "2015-01-18T02:16:03.503Z",
        284.41
      ]
    ]
  }
]

我试过使用 ._map 方法 returns 像这样的地图 (JSFiddle):

var mapped_bill = _.map(bill, function(item) {
    return {"key": item.a, "values": [item.d, item.total]}
});

console.log(JSON.stringify(mapped_bill));

/* returns:
[
  {
    "key": "Paid",
    "values": [
      "2015-01-17T23:58:34.115Z",
      5.21
    ]
  },
  {
    "key": "Scheduled",
    "values": [
      "2015-01-18T02:16:03.503Z",
      374.65
    ]
  },
  {
    "key": "Paid",
    "values": [
      "2015-01-17T23:58:34.115Z",
      310.84
    ]
  },
  {
    "key": "Scheduled",
    "values": [
      "2015-01-18T02:16:03.503Z",
      284.41
    ]
  }
]
*/

如何对上面生成的地图进行分组,以便获得所需的地图?

您可以使用两种 _.map 方法 _.groupBy:

var result = _.map(_.groupBy(data, 'a'), function(el, key) {
    return {
        key: key,
        values: _.map(el, function(item) {
            return [item.d, item.total];
        })
    };
});

查看下面的演示。

var data = [
  {
    "total": 5.21,
    "number": 3,
    "a": "Paid",
    "y": 2015,
    "m": 1,
    "d": "2015-01-17T23:58:34.115Z"
  },
  {
    "total": 374.65,
    "number": 3,
    "a": "Scheduled",
    "y": 2015,
    "m": 1,
    "d": "2015-01-18T02:16:03.503Z"
  },
  {
    "total": 310.84,
    "number": 1,
    "a": "Paid",
    "y": 2015,
    "m": 1,
    "d": "2015-01-17T23:58:34.115Z"
  },
  {
    "total": 284.41,
    "number": 3,
    "a": "Scheduled",
    "y": 2015,
    "m": 1,
    "d": "2015-01-18T02:16:03.503Z"
  }
];

var result = _.map(_.groupBy(data, 'a'), function(el, key) {
    return {
        key: key,
        values: _.map(el, function(item) {
            return [item.d, item.total];
        })
    };
});

pre.innerHTML = JSON.stringify(result, null, 4);
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<pre id="pre"></pre>

根据您的历史记录,可以假定这实际上是一个 问题,即使您只是在查看问题中出现的结果 JavaScript 对象。

因此,根据您提到的结构实际上是 MongoDB 集合的成员,那么生成所需输出的答案将是:

db.mapped.aggregate([
   { "$group": {
       "_id": "$a",
       "values": {
           "$push": {
               "$map": {
                  "input": { "$literal": ["A","B"] },
                  "as": "l",
                  "in": {
                      "$cond": [
                          { "$eq": [ "$$l", "A" ] },
                          "$d",
                          "$total"
                      ]
                  }
               }
           }
       }
   }}
])

因此 $map operator there processes our "two element array template" provided in the $literal operator section, and "transposes" the values via the $cond "ternary" 要么从匹配第一个 "A" 元素的“$d”生成元素,要么从匹配第一个 "A" 元素的元素“$total”生成元素 "A"但因此 "B" 作为唯一的其他合乎逻辑的选择。

结果映射一个数组,该数组具有第一个匹配项的第一个元素和第二个元素作为另一个预期值。然后可以将这些提供给 $push,以根据要求创建和 "array of arrays"。

从您的源中生成一个集合:

{
    "_id" : "Scheduled",
    "values" : [
            [
                    "2015-01-18T02:16:03.503Z",
                    374.65
            ],
            [
                    "2015-01-18T02:16:03.503Z",
                    284.41
            ]
    ]
},
{
    "_id" : "Paid",
    "values" : [
            [
                    "2015-01-17T23:58:34.115Z",
                    5.21
            ],
            [
                    "2015-01-17T23:58:34.115Z",
                    310.84
            ]
    ]
}

所以您并不像您认为的那样需要 JavaScript 中的 post 处理。在服务器端使用适合您的条件的运算符 $group 是您所需要的。