从分组的数组对象中创建一个映射

时间:2015-02-22 18:12:42

标签: javascript underscore.js

我使用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方法返回这样的地图(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
    ]
  }
]
*/

如何将上面生成的地图分组,以便我可以获得所需的地图?

2 个答案:

答案 0 :(得分:3)

您可以对_.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>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

根据您的历史记录,可以假设这实际上是一个问题,即使您只是在查询问题中查看生成的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运算符处理我们的&#34;双元素数组模板&#34;在$literal运算符部分提供,&#34;转置&#34;通过$cond "ternary"的值可以生成元素来自&#34; $ d&#34;第一个&#34; A&#34;元素匹配或元素&#34; $ total&#34;元素不是&#34; A&#34;但因此&#34; B&#34;作为唯一合乎逻辑的选择。

导致映射具有第一个匹配的第一个元素而第二个元素作为另一个期望值的数组。然后可以将这些提供给$push,以创建和&#34;数组阵列&#34;按要求。

从您的来源产生的集合:

{
    "_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中进行这种后期处理。使用适合您服务器端$group条件的运算符即可。