Reputation: 1872
I have some data that I wish to sort into a table. The data consists of an array of rows, which are in turn arrays of cells, which are objects with the properties column_name
, column_value
, column_type
and column_id
(as shown below).
I would like to sort the data by multiple columns, e.g. I would like to sort by city
ascending and then by age
descending. I believe that lodash's _.orberBy()
can achieve this, but I can't work out how to implement it on nested data like this.
Although I suspect lodash will get the job done, I suspect there might be another way that is better.
How would I go about sorting the following, nested data by different columns?
import _ from 'lodash';
const sampleData = [
[
{
column_name: 'id',
column_value: '12345',
column_type: 'string',
column_id: 'item_attributes#id',
},
{
column_name: 'age',
column_value: '32',
column_type: 'number',
column_id: 'item_attributes#age',
},
{
column_name: 'city',
column_value: 'London',
column_type: 'string',
column_id: 'item_attributes#city',
},
],
[
{
column_name: 'id',
column_value: 'abcde',
column_type: 'string',
column_id: 'item_attributes#id',
},
{
column_name: 'age',
column_value: '52',
column_type: 'number',
column_id: 'item_attributes#age',
},
{
column_name: 'city',
column_value: 'Bristol',
column_type: 'string',
column_id: 'item_attributes#city',
},
],
[
{
column_name: 'id',
column_value: 'a1b2d',
column_type: 'string',
column_id: 'item_attributes#id',
},
{
column_name: 'age',
column_value: '21',
column_type: 'number',
column_id: 'item_attributes#age',
},
{
column_name: 'city',
column_value: 'London',
column_type: 'string',
column_id: 'item_attributes#city',
},
],
];
const orderedData = _.orderBy(
sampleData,
// ?? what goes here?
// ?? what goes here?
);
// desired output
// [
// [
// {
// column_name: 'id',
// column_value: 'abcde',
// column_type: 'string',
// column_id: 'item_attributes#id',
// },
// {
// column_name: 'age',
// column_value: '52',
// column_type: 'number',
// column_id: 'item_attributes#age',
// },
// {
// column_name: 'city',
// column_value: 'Bristol',
// column_type: 'string',
// column_id: 'item_attributes#city',
// },
// ],
// [
// {
// column_name: 'id',
// column_value: '12345',
// column_type: 'string',
// column_id: 'item_attributes#id',
// },
// {
// column_name: 'age',
// column_value: '32',
// column_type: 'number',
// column_id: 'item_attributes#age',
// },
// {
// column_name: 'city',
// column_value: 'London',
// column_type: 'string',
// column_id: 'item_attributes#city',
// },
// ],
// [
// {
// column_name: 'id',
// column_value: 'a1b2d',
// column_type: 'string',
// column_id: 'item_attributes#id',
// },
// {
// column_name: 'age',
// column_value: '21',
// column_type: 'number',
// column_id: 'item_attributes#age',
// },
// {
// column_name: 'city',
// column_value: 'London',
// column_type: 'string',
// column_id: 'item_attributes#city',
// },
// ],
// ]
Upvotes: 3
Views: 495
Reputation: 6466
I think this should do what you need. It's easiest to convert each row to a more pleasant object before attempting to use lodash to sort, but we can do that as part of lodash's orderBy
function:
const sampleData = [
[
{
column_name: 'id',
column_value: '12345',
column_type: 'string',
column_id: 'item_attributes#id',
},
{
column_name: 'age',
column_value: '32',
column_type: 'number',
column_id: 'item_attributes#age',
},
{
column_name: 'city',
column_value: 'London',
column_type: 'string',
column_id: 'item_attributes#city',
},
],
[
{
column_name: 'id',
column_value: 'abcde',
column_type: 'string',
column_id: 'item_attributes#id',
},
{
column_name: 'age',
column_value: '52',
column_type: 'number',
column_id: 'item_attributes#age',
},
{
column_name: 'city',
column_value: 'Bristol',
column_type: 'string',
column_id: 'item_attributes#city',
},
],
[
{
column_name: 'id',
column_value: 'a1b2d',
column_type: 'string',
column_id: 'item_attributes#id',
},
{
column_name: 'age',
column_value: '21',
column_type: 'number',
column_id: 'item_attributes#age',
},
{
column_name: 'city',
column_value: 'London',
column_type: 'string',
column_id: 'item_attributes#city',
},
],
];
const rowToNiceObject = row => row.reduce((prev, curr) => {
const thisKey = curr['column_name'];
const thisValue = curr['column_value'];
const newObject = {};
newObject[thisKey] = thisValue;
return Object.assign(prev, newObject);
}, {});
const result = _.orderBy(sampleData, [
row => rowToNiceObject(row).city,
row => rowToNiceObject(row).age
], [
'asc',
'desc'
]);
console.dir(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Upvotes: 1
Reputation: 750
Personally I think you should map your data structure a bit to better suit javascript operations, such as { id: '12345', age: 32, city: 'London'}
. The values can hold the type.
However, with your current data structure you could do sorting like this:
const orderedData = _.orderBy(
sampleData,
entry => entry.find(valueObj => valueObj.column_name==='age').column_value
);
This example uses your 'age'
property. It works by finding the entry in your object collection array, getting the name that describes the age, then comparing by that column_value.
Replacing it with 'city'
or 'id'
works fine.
Upvotes: 2