_.groupBy 但 _.sort 首先

_.groupBy but _.sort first

我得到了这个数组,

我需要在 id 上分组,但首先按 timestamp

排序
sample_array = [
    {id: 21, timestamp:1, year: 2012},
    {id: 11, timestamp:2, year: 2017},
    {id: 12, timestamp:3, year: 2016},
    {id: 11, timestamp:4, year: 2014},
    {id: 11, timestamp:5, year: 2015},
    {id: 19, timestamp:6, year: 2016},
    {id: 12, timestamp:7, year: 2016}
    ]

我尝试使用 underscore.js 实现的是首先使用时间戳对我的数组进行排序,然后检查是否存在相同 ID 的另一个条目,然后在下一个 ID 之前对其进行分组:

预期结果:

[
    {id: 21, timestamp:1, year: 2012},
    {id: 11, timestamp:2, year: 2017},
    {id: 11, timestamp:4, year: 2014},
    {id: 11, timestamp:5, year: 2015},
    {id: 12, timestamp:3, year: 2016},
    {id: 12, timestamp:7, year: 2016},
    {id: 19, timestamp:6, year: 2016}
]

我尝试通过组合使用 _.groupBy_.sortBy 来实现这一点。

需要的是:

  1. 按id分组
  2. 每组按时间戳排序
  3. 按最小时间戳(每个组中的第一个时间戳)对组进行排序

如果这个数组有问题,你可以简单地解决如下问题,你可以玩数字如果零添加到时间戳,并为每个时间戳取确切的数字:),检查它应该工作(这个例子是最大的5 位数的时间戳)如果它有更多你可以在开头添加零

    sample_array.sort(function(a,b){
return Number(a.id.toString()+('00000'+a.timestamp.toString()).substr(a.timestamp.toString().length-1))-Number(b.id.toString()+('00000'+b.timestamp.toString()).substr(b.timestamp.toString().length-1))
})

基于下一个理解:

group by id, sort by timestamp in each group then sort groups by their minimum timestamp(first timestamp in each group actually) and flatten groups into flat list.

_.chain(sample_array)
 .groupBy('id')
 .mapObject(groupPerId=> _.sortBy(groupPerId, 'timestamp'))
 .sortBy(groupPerId=> groupPerId[0].timestamp)
 .flatten()
 .value()

您可以按 timestamp 排序,然后按 id 排序,但不要取数字,因为数字在对象中排在最前面。因此,您需要将数字转换为字符串并对其进行分组。

然后映射值并展平数组。

var array = [{ id: 21, timestamp:1, year: 2012 }, { id: 11, timestamp:2, year: 2017 }, { id: 12, timestamp:3, year: 2016 }, { id: 11, timestamp:4, year: 2014 }, { id: 11, timestamp:5, year: 2015 }, { id: 13, timestamp:6, year: 2016 }, { id: 12, timestamp:7, year: 2016 }],
    result = _.chain(array)
        .sortBy(['timestamp'])
        .groupBy(o => _ + o.id)
        .map(v => v)
        .flatten()
        .value();

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>