Luigi Lake
Luigi Lake

Reputation: 31

How do I sort an array of strings numerically with Ramda?

I'm trying to sort the following object's keys properly:

const data = {
  '0 - 4': [...],
  '5 - 9': [...],
  '10 - 14': [...],
  '15 - 19': [...],
};

By doing:

const sort = R.sortBy(R.toLower);
return R.compose(sort, R.keys)(data);

But it always ends up coming out as:

['0 - 4', '10 - 14', '15 - 19', '5 - 9'];

Because it's treating the numbers as a string and a string that starts with 5 is supposedly higher than a string that starts with a 1. Would anyone know how to use Ramda to properly sort this so that it comes out as

['0 - 4', '5 - 9', '10 - 14', '15 - 19'];

Upvotes: 3

Views: 634

Answers (2)

ibrahim mahrir
ibrahim mahrir

Reputation: 31692

Use parseInt instead of R.toLower:

const sort = R.sortBy(parseInt);

R.toLower doesn't make sense because it won't affect the strings anyway because they only contain numbers, dashes and spaces, and the result of calling toLower will still be a string, the same string.

parseInt, on the other hand, will return the left-side number of each string (for example parseInt('10 - 14') is the number 10, not a string), which will then be used by sortBy to sort the strings.

Demo:

const data = {
  "10 - 14'": [],
  "5 - 9": [],
  "15 - 19": [],
  "0 - 4": []
};

const sort = R.sortBy(parseInt);
const result = R.compose(sort, R.keys)(data);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 191986

You can use String.localCompare() with the numeric: true option in the comparator function:

const data = {
  '0 - 4': [],
  '5 - 9': [],
  '10 - 14': [],
  '15 - 19': [],
};

const sort = R.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));

const result = R.compose(sort, R.keys)(data);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

And this is how you would do that without Ramda:

const data = {
  '0 - 4': [],
  '5 - 9': [],
  '10 - 14': [],
  '15 - 19': [],
};

const fn = obj => 
  Object.keys(obj)
    .sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));

const result = fn(data);

console.log(result);

Upvotes: 3

Related Questions