Ivan Akulov
Ivan Akulov

Reputation: 4323

Wrap the function into another function

I have the code that sorts an array of objects by the object property using lodash. It’s pretty simple:

_.sortBy(data.cycles, "id");

However, I discovered that data.cycles[].id might be a string, so I have to convert each property to number before passing it to _.sortBy. Is there any elegant way of doing it? I think I should combine _.property and parseInt somehow, but I don’t know how.

data.cycles might look like this:

[
  {
    "id": "20",
    "name": "John"
  },
  {
    "id": "15",
    "name": "Sarah"
  },
  {
    "id": "158",
    "name": "Bill"
  },
  {
    "id": "-6",
    "name": "Jack"
  },
  {
    "id": "59",
    "name": "Bob"
  }
]

Upvotes: 1

Views: 984

Answers (2)

Adam Boduch
Adam Boduch

Reputation: 11211

I would compose a sortBy() callback as follows:

var collection = [
    { id: '20', name: 'John' },
    { id: 15, name: 'Sarah' },
    { id: 158, name: 'Bill' },
    { id: '-6', name: 'Jack' },
    { id: 59, name: 'Bob' }
];

_.sortBy(collection, _.flow(_.property('id'), parseInt));
// →
// [
//   { id: '-6', name: 'Jack' },
//   { id: 15, name: 'Sarah' },
//   { id: '20', name: 'John' },
//   { id: 59, name: 'Bob' },
//   { id: 158, name: 'Bill' }
// ]

The flow() function is useful when you want to compose a callback function out of many functions, it just forwards the output to the next function in line. The property() function returns a function that gets the specified property name from it's argument. This is the id, and that gets passed to parseInt().

We're essentially mapping and sorting at the same time. This has an efficiency advantage, in addition to being a one-liner: it doesn't have to iterate over the whole collection twice. This isn't a big deal with smaller collections, but with larger collections, the impact is noticeable.

Upvotes: 2

Joseph
Joseph

Reputation: 119847

You might want to run map first and modify id, then do a sort.

In vanilla JS, it would look something like:

function mapFn(item){
  item.id = parseInt(item.id, 10);
  return item;
}

var sortedCycles = data.cycles.map(mapFn).sort(sortFn);

In lodash, you could have:

var sortedCycles = _.sortBy(_.map(data.cycles, mapFn), 'id');
// or
var sortedCycles = _.chain(data.cycles).map(mapFn).sortBy('id').value()

Upvotes: 1

Related Questions