Berlin Sianipar Berlin Sianipar - 5 months ago 11x
Javascript Question

How to sort mixed formatted numbers (89, 900, 1k, 1.5k, 15.2k)

I'm trying to pull out some strings from a website (Pinterest, to be specific), and sort out the strings. The problem is that the strings contain both numbers and text(k for thousands and m for millions).

list.sort(function(a, b) {
var compA = Number( $(a).find('.repinCountSmall').text().trim().replace(/[^0-9]/g, '') );
var compB = Number( $(b).find('.repinCountSmall').text().trim().replace(/[^0-9]/g, '') );
return (compA == compB) ? 0 : (compA > compB) ? -1 : 1;

With the above code, if I have .repinCountSmall list function that provides the following:








The problem with the current function is that it strips "k" in 1.7k and arrives at 17. Similarly 17.3k, and 1.2m is treated as 173 and 12 respectively. I want the numbers ending with k multiplied by 1000 first, and string ending with m to be multiplied with 1000000 respectively. The list should sorted after this conversion.

Any solutions? Thanks.


You could use a conversion function something like this (obviously you could add some additional else if statements if you had to allow for multipliers other than "k" and "m"):

function toNumber(s) {
  s = s.replace(/[^\dkm.]/g,"");
  var u = s.slice(-1);
  if (u === "k")
    return s.slice(0,-1) * 1000;
  else if (u === "m")
    return s.slice(0,-1) * 1000000;
  return +s;

And then reference that from within your .sort() comparator function:

list.sort(function(a,b) {
  var n1 = toNumber($(a).find('.repinCountSmall').text());
  var n2 = toNumber($(b).find('.repinCountSmall').text());
  return n1 - n2;

Note also that you don't need nested ternary operators to compare the resulting two numbers: because they are numbers you can just return the result of subtracting one from the other.