1

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.

3

3 Answers 3

5

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)
))

Sign up to request clarification or add additional context in comments.

4 Comments

To sort objects like {v: "7"}, replace comparator(a, b) by comparator({v: a}, {v: b}).
@Luca, Thanks. It is clear. Could you please also explain how I can use it in event listener? Currently, I am using answer of following stack overflow post for sort on even: stackoverflow.com/questions/20166551/…
As long as you have a variable that has the array, you can just plug that function in there.
@Luca, I tried, but still could not make it work, because some how I need to add 'event' in your code. The original one that I am using is: data.sort([{column: event.column, desc: !event.ascending}]);. How can I change your code such that a and b refers to entries of even.column?
1

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"]

Comments

1

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);

3 Comments

It looks to me that the OP may be using string values, so you may have to change your example a bit
Thanks @Nina. Actually, it is like a event listener that needs to always sort it when the column is selected in html.
Can you please explain that comparator a bit more? It is hard to make sense of

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.