_.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
来实现这一点。
需要的是:
- 按id分组
- 每组按时间戳排序
- 按最小时间戳(每个组中的第一个时间戳)对组进行排序
如果这个数组有问题,你可以简单地解决如下问题,你可以玩数字如果零添加到时间戳,并为每个时间戳取确切的数字:),检查它应该工作(这个例子是最大的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>
我得到了这个数组,
我需要在 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
来实现这一点。
需要的是:
- 按id分组
- 每组按时间戳排序
- 按最小时间戳(每个组中的第一个时间戳)对组进行排序
如果这个数组有问题,你可以简单地解决如下问题,你可以玩数字如果零添加到时间戳,并为每个时间戳取确切的数字:),检查它应该工作(这个例子是最大的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>