Javascript ES6 custom sort method not working all

2019-08-13 19:03发布

问题:

I want to sort my JSON output.

I made my own sort method for it as you can see here:

const sortAsc = (propertyName) => (a, b) => a[propertyName] === b[propertyName] ? 0 : a[propertyName] < b[propertyName] ? -1 : 1;
const sortDesc = (propertyName) => (a, b) => a[propertyName] === b[propertyName] ? 0 : a[propertyName] < b[propertyName] ? 1 : -1;

I call it like so:

asc(value) {
    this.result.sort(this.sortAsc(value));
}

It works sort of but when I sort it it doesn't sort right always.

Take a look at this little gif: https://gyazo.com/5f590f7c921eb1cb3bc4138f85c2162b

As you see it doesn't really work with the ID. It works ascending on Naam (name in dutch) But when descending it first gives 2 names starting with v & k. Why is that?

Well, If that's something what is hard to be fixed it isn't really a problem. As long it can sort numbers aswell as strings.

One more thing to note is that I am using Angular 4.4.4. I googled for a build-in sort/orderBy function but found that's not build-in. But if there is anything I can use that Angular provides to make it easier I would be happy to use it!

EDIT:

My new methods:

sortAsc = (propertyName) => (a, b) => a[propertyName].localeCompare(b[propertyName]);

回答1:

You could use String#localeCompare with option:

The localeCompare() method returns a number indicating whether a reference string comes before or after or is the same as the given string in sort order.

The new locales and options arguments let applications specify the language whose sort order should be used and customize the behavior of the function. In older implementations, which ignore the locales and options arguments, the locale and sort order used are entirely implementation dependent.

const sortAsc = propertyName => (a, b) =>
    a[propertyName].localeCompare(b[propertyName], undefined, { numeric: true, sensitivity: 'base' });


const sortDesc = (propertyName) => (a, b) =>
    -a[propertyName].localeCompare(b[propertyName], undefined, { numeric: true, sensitivity: 'base' });


回答2:

I guess you want to compare Ids as numbers, so you should use appropriate sorting functions for number-like columns:

const sortAsc = (propertyName) => (a, b) => a[propertyName] === b[propertyName] ? 0 : +a[propertyName] < +b[propertyName] ? -1 : 1;
const sortDesc = (propertyName) => (a, b) => a[propertyName] === b[propertyName] ? 0 : +a[propertyName] < +b[propertyName] ? 1 : -1;

Another way is to adjust you table data array, ids should be numbers there, not strings, in this case your sorting functions should also work.



回答3:

Your comparison functions are totally fine. The relational operators work out of the box on both numbers and strings, there's no reason to use localeCompare.

It works sort of but when I sort it it doesn't sort right always: it doesn't really work with the ID.

It appears that the id properties in your array of objects are strings, so they are compared lexicographically. Make them actual numbers and they'll be compared as numbers.

It works ascending on Naam But when descending it first gives 2 names starting with v & k. Why is that?

It's really hard to see in the gif, but it appears that those two weirdly sorted values begin with a space - which is always sorted first. Make sure your data is valid.