Pierre Olivier Tran
Pierre Olivier Tran

Reputation: 1875

Lodash - Sort by position in array

I have an array of objects

let myArray = [
    {
        id: 'first',
        name: 'john',
    },
    {
        id: 'second',
        name: 'Emmy',
    },
    {
        id: 'third',
        name: 'Lazarus',
    }
]

and an array

let sorter = ['second', 'third', 'first']

I would like to use lodash sorting method to sort my objects according to their position in sorter. So that the output would be

let mySortedArray = [
    {
        id: 'second',
        name: 'Emmy',
    },
    {
        id: 'third',
        name: 'Lazarus',
    },
    {
        id: 'first',
        name: 'john',
    }
]

Is it possible to do so?

Upvotes: 2

Views: 3231

Answers (4)

Akrion
Akrion

Reputation: 18515

Since you have an index array in the case of the sorter you can _.keyBy the main array and then use the sorter to access by index:

let myArray = [ { id: 'first', name: 'john', }, { id: 'second', name: 'Emmy', }, { id: 'third', name: 'Lazarus', } ]
let sorter = ['second', 'third', 'first']

const idMap = _.keyBy(myArray, 'id')
const result = _.map(sorter, x => idMap[x])

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

This should perform better since you only do the idMap once and then access it by index.

Upvotes: 0

VLAZ
VLAZ

Reputation: 29009

If you want to sort the array in-place, you don't need Lodash, you can easily do it with vanilla JavaScript

let myArray = [
    {
        id: 'first',
        name: 'john',
    },
    {
        id: 'second',
        name: 'Emmy',
    },
    {
        id: 'third',
        name: 'Lazarus',
    }
]

let sorter = ['second', 'third', 'first']

//create a lookup table (map) to save looking through the array
const sortLookup = new Map(); 
//populate with element as key - index as value
sorter.forEach((id, index) => sortLookup.set(id, index));

//sort using the indexes of sorter 
myArray.sort((a, b) => sortLookup.get(a.id) - sortLookup.get(b.id))

console.log(myArray)

This is using a Map but the same can easily be accomplished with a plain JavaScript Object {}. You don't even need to pre-compute the lookup myArray.sort((a, b) => sorter.indexOf(a.id) - sorter.indexOf(b.id)) would give the exact same output but it would mean that instead of traversing sorter once for a complexity of O(n), you potentially have O(n^m)or O(n^n) (if both arrays are the same length)

Upvotes: 0

George
George

Reputation: 6739

Using lodash you can use _.sortBy

let myArray = [
    {
        id: 'first',
        name: 'john',
    },
    {
        id: 'second',
        name: 'Emmy',
    },
    {
        id: 'third',
        name: 'Lazarus',
    }
]

let sorter = ['second', 'third', 'first']

console.log(_.sortBy(myArray,(i) => {return sorter.indexOf(i.id)})) 
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>

Upvotes: 3

Alberto Trindade Tavares
Alberto Trindade Tavares

Reputation: 10366

You can achieve this by using map and find:

let myArray = [
  {
    id: "first",
    name: "john"
  },
  {
    id: "second",
    name: "Emmy"
  },
  {
    id: "third",
    name: "Lazarus"
  }
];

let sorter = ["second", "third", "first"];

let mySortedArray = sorter.map(x => myArray.find(y => y.id === x));

console.log(mySortedArray);

Upvotes: 5

Related Questions