Berlin Sianipar Berlin Sianipar - 7 months ago 18
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:

1

250

999

1k

1.7k

17.3k

1.2m

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.

Answer

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.