Using lodash I’d like to be able to sort an array of objects like below (but much larger) by several keys, some of which are nested in arrays: The precedence would be:
- Ine to a given year (ie provide (say) 2012 and ine would be used for that year for all elements)
- displayInGraph (being true)
- pinnedRow (being true)
I’d also like to be able to reverse the above.
I've looked in the lodash documentation but cannot see the solution to my question:
[{
displayInGraph: true,
pinnedRow: true,
dateRange: [{
year: 2010,
ine: 20000
}, {
year: 2011,
ine: 30000
}, {
year: 2012,
ine: 40000
}, {
year: 2013,
ine: 44000
}]
},
{
displayInGraph: true,
pinnedRow: false,
dateRange: [{
year: 2010,
ine: 20000
}, {
year: 2011,
ine: 32500
}, {
year: 2012,
ine: 50000
}, {
year: 2013,
ine: 45200
}]
},
{
displayInGraph: true,
pinnedRow: false,
dateRange: [{
year: 2010,
ine: 20400
}, {
year: 2011,
ine: 38000
}, {
year: 2012,
ine: 30000
}, {
year: 2013,
ine: 45000
}]
},
{
displayInGraph: true,
pinnedRow: true,
dateRange: [{
year: 2010,
ine: 21030
}, {
year: 2011,
ine: 39000
}, {
year: 2012,
ine: 44000
}, {
year: 2013,
ine: 45400
}]
}
]
Using lodash I’d like to be able to sort an array of objects like below (but much larger) by several keys, some of which are nested in arrays: The precedence would be:
- Ine to a given year (ie provide (say) 2012 and ine would be used for that year for all elements)
- displayInGraph (being true)
- pinnedRow (being true)
I’d also like to be able to reverse the above.
I've looked in the lodash documentation but cannot see the solution to my question:
[{
displayInGraph: true,
pinnedRow: true,
dateRange: [{
year: 2010,
ine: 20000
}, {
year: 2011,
ine: 30000
}, {
year: 2012,
ine: 40000
}, {
year: 2013,
ine: 44000
}]
},
{
displayInGraph: true,
pinnedRow: false,
dateRange: [{
year: 2010,
ine: 20000
}, {
year: 2011,
ine: 32500
}, {
year: 2012,
ine: 50000
}, {
year: 2013,
ine: 45200
}]
},
{
displayInGraph: true,
pinnedRow: false,
dateRange: [{
year: 2010,
ine: 20400
}, {
year: 2011,
ine: 38000
}, {
year: 2012,
ine: 30000
}, {
year: 2013,
ine: 45000
}]
},
{
displayInGraph: true,
pinnedRow: true,
dateRange: [{
year: 2010,
ine: 21030
}, {
year: 2011,
ine: 39000
}, {
year: 2012,
ine: 44000
}, {
year: 2013,
ine: 45400
}]
}
]
Thanks in advance for solutions
Share Improve this question edited Jan 24, 2018 at 0:26 user2190690 asked Jan 24, 2018 at 0:03 user2190690user2190690 2,0444 gold badges26 silver badges32 bronze badges 2- 1 fyi, your snippet is not valid javascript, (there are no keys for your year/ine arrays). – CRice Commented Jan 24, 2018 at 0:10
- @CRice, thank you - edited... – user2190690 Commented Jan 24, 2018 at 0:26
3 Answers
Reset to default 6You can use lodash to sort by multiple properties within an object by having the iterated function return an array of the properties that you want to sort. This example will sort by property a
, then property b
, then property sortkey
.
var input = [
{ a: 4, b: 5, data: 9, sortkey: "blue" },
{ a: 3, b: 9, data: 27, sortkey: "red" },
{ a: 3, b: 9, data: 4, sortkey: "green" },
{ a: 3, b: 3, data: 19, sortkey: "purple" },
{ a: 4, b: 3, data: 6, sortkey: "white" },
{ a: 5, b: 0, data: 0, sortkey: "orange" }
];
var output = _.sortBy(input, function(o) {
return [o.a, o.b, o.sortkey];
});
See fiddle: https://jsfiddle/mikeular/qog6h9ez/3/ .
You could then reverse the sort behavior by updating the array. For example, if you wanted a
ascending, b
descending, and sortkey
ascending, you can do something like:
var output = _.sortBy(input, function(o) {
return [o.a, -1 * o.b, o.sortkey];
});
(I prefer -1 * o.b
over -o.b
to elevate the visibility of the reversal).
It would be a fun exercise to see how it performs vs the somewhat cleaner:
var output = _.sortBy(input, ['a', 'b', 'sortkey']);
...if performance is relevant to you.
Lodash has a _.sortBy
method which accepts as it's second argument either a string (as a path to the sort property), or a function (which returns the sort property), or an array thereof. So you can sort on multiple parameters by using an array of sort functions:
const myArray = [{
displayInGraph: true,
pinnedRow: true,
dateRange: [{
year: 2010,
ine: 20000
}, {
year: 2011,
ine: 30000
}, {
year: 2012,
ine: 40000
}, {
year: 2013,
ine: 44000
}]
},
{
displayInGraph: true,
pinnedRow: false,
dateRange: [{
year: 2010,
ine: 20000
}, {
year: 2011,
ine: 32500
}, {
year: 2012,
ine: 50000
}, {
year: 2013,
ine: 45200
}]
},
{
displayInGraph: true,
pinnedRow: false,
dateRange: [{
year: 2010,
ine: 20400
}, {
year: 2011,
ine: 38000
}, {
year: 2012,
ine: 30000
}, {
year: 2013,
ine: 45000
}]
},
{
displayInGraph: true,
pinnedRow: true,
dateRange: [{
year: 2010,
ine: 21030
}, {
year: 2011,
ine: 39000
}, {
year: 2012,
ine: 44000
}, {
year: 2013,
ine: 45400
}]
}
]
console.log(_.sortBy(myArray, [
item => (item.dateRange.find(range => range.year === 2012) || {ine: 0}).ine,
item => item.displayInGraph,
item => item.pinnedRow,
]));
<script src="https://cdnjs.cloudflare./ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Finally, you can reverse the result by using the javascript built in array .reverse
method.
Have you tried with sortBy? It can receive a list of functions used to perform each step of the sort.
For example you can:
const year = 2012;
const getIne = (obj) => _.find(obj.dateRange, {ine: year});
_.sortBy(users, [getIne, 'displayInGraph', 'pinnedRow']);