Issue sorting columns containing the same value when browsers have implemented an unstable `Array.prototype.sort(comparefn)`
See original GitHub issueThe property of a sorting algorithm that leaves elements that compare as equal in their original list order is called stability. The JavaScript spec specifically allows for implementations to use unstable sort algorithms; no version of Chrome adopts a stable sorting implementation.
The sort is not necessarily stable (that is, elements that compare equal do not necessarily remain in their original order).
It is possible to get a stable sorting from a non-stable sort function. Before sorting you get the position of all the elements. In your sort condition, if both elements are equal, then you sort by the position.
Below is a modified initSort()
solving the issue described above - would you be interested in a PR for this change?
if (!Object.keys) {
Object.keys = function(obj) {
var keys = [];
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
keys.push(i);
}
}
return keys;
};
}
BootstrapTable.prototype.initSort = function () {
var that = this,
name = this.options.sortName,
order = this.options.sortOrder === 'desc' ? -1 : 1,
index = $.inArray(this.options.sortName, this.header.fields),
length = Object.keys(this.data).length;
// Add current position to data object in order to enable a stable sort
// for times when values are compared as equal
for (var key in this.data) {
if (this.data.hasOwnProperty(key)) {
// Save position
this.data[key].position = key;
}
}
if (index !== -1) {
this.data.sort(function (a, b) {
if (that.header.sortNames[index]) {
name = that.header.sortNames[index];
}
var aa = getItemField(a, name),
bb = getItemField(b, name),
value = calculateObjectValue(that.header, that.header.sorters[index], [aa, bb]);
if (value !== undefined) {
return order * value;
}
// Fix #161: undefined or null string sort bug.
if (aa === undefined || aa === null) {
aa = '';
}
if (bb === undefined || bb === null) {
bb = '';
}
// Found to be equal
if (aa === bb) {
var aa_position = getItemField(a, 'position'),
bb_position = getItemField(b, 'position');
if (order == 1) {
aa = (length - aa_position),
bb = (length - bb_position);
} else {
aa = aa_position,
bb = bb_position;
}
}
// If both values are numeric, do a numeric comparison
if ($.isNumeric(aa) && $.isNumeric(bb)) {
// Convert numerical values form string to float.
aa = parseFloat(aa);
bb = parseFloat(bb);
if (aa < bb) {
return order * -1;
}
return order;
}
// If value is not a string, convert to string
if (typeof aa !== 'string') {
aa = aa.toString();
}
if (aa.localeCompare(bb) === -1) {
return order * -1;
}
return order;
});
}
};
Issue Analytics
- State:
- Created 8 years ago
- Comments:9 (7 by maintainers)
Top Results From Across the Web
Array.prototype.sort(compareFn) works different in browsers?
A stable sorting algorithm returns equal list items in the same order as they appear originally, whereas an unstable sorting algorithm does not....
Read more >Implement a stable sorting algorithm #14412 - GitHub
The user can't just click on two columns in order and expect the first column to still be sorted for any given value...
Read more >Array.prototype.sort() - JavaScript - MDN Web Docs
The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted. The default...
Read more >Sorting in JavaScript: Handling Google Chrome's Unstable Sort
That's called a "stable" sort. Now, the problem with the Array.prototype.sort method is that different browsers implement it differently.
Read more >90 - V8 doesn't stable sort - Monorail
I think it's absolutely unacceptable that sorting is unstable merely due to the size of the array. I have no problem with v8...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I think this is an important fix for our plugin
If a custom sorter is set on a column the fix doesn’t work. if (value !== undefined) { return order * value; } doesn’t handle the equality problem