Search code examples
javascriptarraysfunctional-programminglodash

Sorting multiple rows of data in JavaScript with lodash


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',
//     },
//   ],
// ]

Solution

  • 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.