简体   繁体   English

如何使用Lodash在特定字段上的JavaScript对象数组进行分组?

[英]How to group an array of objects in JavaScript on specific fields using Lodash?

EDIT: I believe this is a different problem than a simple _.groupBy because I am trying to group by all keys and returning an hashmap not an array. 编辑:我认为这是一个比简单的_.groupBy不同的问题,因为我试图按所有键进行分组并返回哈希图而不是数组。


I have an array of the following objects: 我有以下对象的数组:

items = [
  { created_at: "01/01/2016", name: "bob", age: 21, height: 60 },
  { created_at: "01/02/2016", age: 22, height: 70 },
  { created_at: "01/03/2016", name: "alice", age: 23 }
]

And I am trying to transform it into this format: 我正在尝试将其转换为以下格式:

{
  "name": [
    {
      "value": "bob",
      "created_at": "01/01/2016"
    },
    {
      "value": "alice",
      "created_at": "01/03/2016"
    }
  ],
  "age": [
    {
      "value": 21,
      "created_at": "01/01/2016"
    },
    {
      "value": 22,
      "created_at": "01/02/2016"
    },
    {
      "value": 23,
      "created_at": "01/03/2016"
    }
  ],
  "height": [
    {
      "value": 60,
      "created_at": "01/01/2016"
    },
    {
      "value": 70,
      "created_at": "01/02/2016"
    }
  ]
}

My requirement is I am ignoring the created_at field, but grouping everything else. 我的要求是我忽略了created_at字段,但将其他所有内容分组。

One solution is: 一种解决方案是:

 var items = [ { created_at: "01/01/2016", name: "bob", age: 21, height: 60 }, { created_at: "01/02/2016", age: 22, height: 70 }, { created_at: "01/03/2016", name: "alice", age: 23 } ] var store = {} for(var i=0; i < items.length; i++) { var item = items[i] for(key in item) { if(key === "created_at") { continue } value = item[key] if(!store[key]) { store[key] = [] } store[key].push({ value: value, created_at: item.created_at }) } } $('pre').text(JSON.stringify(store, null, 2)) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body><pre></pre></body> 

I was wondering if there was some cool way to do it in lodash ... maybe using .map() or .groupBy() or something? 我想知道是否有一些很酷的方法可以在lodash使用它……也许使用.map().groupBy()东西? I don't quite get how to use them properly and am trying to learn new, more elegant ways to write the code. 我不太了解如何正确使用它们,而是试图学习新的,更优雅的代码编写方法。

Using reduce might be the shortest way. 使用reduce可能是最短的方法。

var baseKey = 'created_at';

var result = items.reduce(function(col, item) {
  Object.keys(item).forEach(function(key) {
    if (key === baseKey || !item[key]) return;
    var o = { value: item[key] };
    o[baseKey] = item[baseKey];
    (col[key] = col[key] || []).push(o);
  });
  return col;
}, {});

JSFiddle Demo: https://jsfiddle.net/pLcv1am2/6/ JSFiddle演示: https ://jsfiddle.net/pLcv1am2/6/

You asked specifically about lodash, and so this answer is constructed using lodash. 您是专门询问lodash的,所以此答案是使用lodash构造的。

Note I'm using the _.chain method - this makes it convenient to chain multiple operations rather than running them each separately. 注意我正在使用_.chain方法-这使链接多个操作而不是分别单独运行它们很方便。

One way (I'm sure there are many others) that gets it pretty close (not perfect) is this: 一种非常接近(不完美)的方式(我敢肯定还有很多其他方式)是这样的:

items = _.chain(items)
  .map(function(n) {
    var created = _.get(n, 'created_at');
    var arr = [];
    _.each(n, function(n, k) {
      if (k != 'created_at') {
        arr.push({
          'field': k,
          'value': n,
          'created_at': created
        });
      }
    });
    return arr;
  })
  .flatten()
  .groupBy('field')
  .value();

Which results in a collection that looks like this: 结果是一个看起来像这样的集合:

{ "name": 
    [ 
        { "field": "name", "value": "bob", "created_at": "01/01/2016" }, 
        { "field": "name", "value": "alice", "created_at": "01/03/2016" } 
    ], 
  "age": [
     ....

Here's a Fiddle for playing around with this code. 这是一个玩弄此代码的小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM