Reputation: 1242
I got this array,
I need to group on id
, but first sort it by 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}
]
What i try to achieve using underscore.js
is to sort my array using timestamp first, but then check if exists another entry for same id, then group on it before next id:
expected results :
[
{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}
]
I try to achieve this by using combination of _.groupBy
and _.sortBy
.
The need is to :
Upvotes: 1
Views: 410
Reputation: 386550
You could sort by timestamp
and then sort by id
, but do not take the number, because numbers are sorted to top in objects. Therefore you need to convert the number to a string and group by it.
Then map the values and flatten the arrays.
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>
Upvotes: 2
Reputation: 1120
If this array is the problem, you can solve simply as follows, you can play with digits if zeros adding to timestamp, an taking the exact number for each timestamp :), check it should work (this example is maximum 5 digits of timestamp) if it has more you can add zeros at beginings
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))
})
Upvotes: 0
Reputation: 23705
Based on next understanding:
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()
Upvotes: 1