Shannon
Shannon

Reputation: 1205

Sort String-Type Columns in JavaScript

I was wondering how I can sort a column which has either digit or 'x' value (for not defined). With conventional sort, the result is not correct and 17 comes sooner than 7.

Example:

17   
7    
9    
X

Want to sort it like:

7    
9    
17   
X

PS.
I am using:

var data = new google.visualization.DataTable()
data.addRow[{v:'17'}, {v:'7'}, {v:'9'}, {v:'X'}]

I want to be able to sort it in the event listener.

Upvotes: 1

Views: 379

Answers (3)

Nina Scholz
Nina Scholz

Reputation: 386680

You could sort with a check for 'X' and move this value to the end of the array.

By taking Array#sort without callback, all items are sorted as strings.

The sorting takes place in two parts,

  1. checking for NaN and taking the delta of the boolean results, which means,

     value   value  isNaN  isNaN
       a       b      a      b    delta  meaning
    ------  ------  -----  -----  -----  -------
      NaN     NaN    true   true    0   a === b
      NaN   number   true  false    1   a  >  b
    number    NaN   false   true   -1   a  <  b
    number  number  false  false    0   a === b
    
  2. take the delta of the values

var array = [{ v: '17' }, { v: 'X' }, { v: '7' }, { v: '9' }];

array.sort(({ v: a }, { v: b }) => isNaN(a) - isNaN(b) || a - b);

console.log(array);

Upvotes: 1

Luca Kiebel
Luca Kiebel

Reputation: 10096

You can use localeCompare with the {numeric:true} option in a comparator function:

let arr = ["17","7","9","X"];

function comparator(a,b) {
  return a.localeCompare(b, "en", {numeric:true});
}

console.log(
  arr.sort(comparator)
)

If your array is of this format

[{ v: '17' }, { v: 'X' }, { v: '7' }, { v: '9' }];

You have to adapt the comparator a bit:

var arr = [{ v: '17' }, { v: 'X' }, { v: '7' }, { v: '9' }];

function comparator(a,b) {
  return a.v.localeCompare(b.v, "en", {numeric:true});
}

console.log(JSON.stringify(
  arr.sort(comparator)
))

Upvotes: 5

bozdoz
bozdoz

Reputation: 12870

You want localeCompare.

// by default, "2" > "10"
console.log("2".localeCompare("10")); // 1

// numeric using options:
console.log("2".localeCompare("10", undefined, {numeric: true})); // -1

You can use this in a sort function (MDN):

["17", "7", "9", "X"].sort(function(a,b) {
  return a.localeCompare(b, undefined, {numeric: true})
})
// ["7", "9", "17", "X"]

Upvotes: 1

Related Questions