【问题标题】:How to group an array of objects in JavaScript on specific fields using Lodash?如何使用 Lodash 在特定字段上对 JavaScript 中的对象数组进行分组?
【发布时间】:2016-05-05 07:41:56
【问题描述】:

编辑: 我相信这是一个与简单的_.groupBy 不同的问题,因为我试图按所有键分组并返回一个哈希图而不是数组。


我有以下对象的数组:

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 }
]

我正在尝试将其转换为这种格式:

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

我的要求是我忽略created_at 字段,但将其他所有内容分组。

一种解决方案是:

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>

我想知道在lodash 中是否有一些很酷的方法可以做到这一点......也许使用.map().groupBy() 或其他什么?我不太了解如何正确使用它们,我正在尝试学习新的、更优雅的代码编写方式。

【问题讨论】:

  • 这是一个不同的问题,因为其他的只按一个字段分组并生成一个数组。我正在按键分组并生成一个对象。
  • 你拥有它的方式看起来很简单。 _.groupBy 可能会增加不必要的复杂性。不要使用你不需要的东西。
  • 是的,因为我不经常使用许多 lodash 附加方法,所以我不确定是否有一种“单线”类型的方法可以产生与我相同的结果

标签: javascript lodash


【解决方案1】:

使用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 演示:https://jsfiddle.net/pLcv1am2/6/

【讨论】:

    【解决方案2】:

    您专门询问了 lodash,所以这个答案是使用 lodash 构造的。

    请注意,我使用的是_.chain 方法 - 这样可以方便地链接多个操作,而不是单独运行它们。

    一种非常接近(不完美)的方法(我相信还有 许多 其他方法)是这样的:

    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();
    

    这会产生如下所示的集合:

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

    Here's a Fiddle 玩弄这段代码。

    【讨论】:

      猜你喜欢
      • 2022-01-17
      • 1970-01-01
      • 2020-10-21
      • 2021-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-28
      相关资源
      最近更新 更多