PDA

View Full Version : grid stable sort



ericwaldheim
28 Nov 2006, 8:17 AM
drop-in replacement for DefaultDataModel sort:



YAHOO.ext.grid.DefaultDataModel.prototype.sort = function(sortInfo, columnIndex, direction, suppressEvent){
// store these so we can maintain sorting when we load new data
this.sortInfo = sortInfo;
this.sortColumn = columnIndex;
this.sortDir = direction;

var dsc = (direction && direction.toUpperCase() == 'DESC');
var sortType = null;
if(sortInfo != null){
if(typeof sortInfo == 'function'){
sortType = sortInfo;
}else if(typeof sortInfo == 'object'){
sortType = sortInfo.getSortType(columnIndex);;
}
}
var data = this.data;
var ds = [];
for (var i = 0; i < data.length; ++i)
ds.push([data[i][columnIndex], i]);

var fn = function(d1, d2){
var v1 = sortType ? sortType(d1[0], d1) : d1[0];
var v2 = sortType ? sortType(d2[0], d2) : d2[0];
if (v1 < v2) return dsc ? +1 : -1;
if (v1 > v2) return dsc ? -1 : +1;
if (d1[1] < d2[1]) return dsc ? +1 : -1;
return dsc ? -1 : +1;
};
ds.sort(fn);
var newData = [];
for (var i = 0; i < ds.length; ++i)
newData[i] = data[ds[i][1]];
this.data = newData;

if (!suppressEvent){
this.fireRowsSorted(columnIndex, direction);
}
}

jack.slocum
28 Nov 2006, 8:49 AM
What does it do differently?

jack.slocum
28 Nov 2006, 8:55 AM
Ah I just saw the title. Cool.

ericwaldheim
28 Nov 2006, 12:00 PM
This one is more efficient:


YAHOO.ext.grid.DefaultDataModel.prototype.sort = function(sortInfo, columnIndex, direction, suppressEvent){
// store these so we can maintain sorting when we load new data
this.sortInfo = sortInfo;
this.sortColumn = columnIndex;
this.sortDir = direction;

var dsc = (direction && direction.toUpperCase() == 'DESC');
var sortType = null;
if(sortInfo != null){
if(typeof sortInfo == 'function'){
sortType = sortInfo;
}else if(typeof sortInfo == 'object'){
sortType = sortInfo.getSortType(columnIndex);;
}
}
var data = this.data;
var ds = [];
for (var i = 0; i < data.length; ++i)
{
var row = data[i];
var value = row[columnIndex];
value = sortType ? sortType(value, row) : value;
ds.push([value, i]);
}

var fn = function(d1, d2){
if (d1[0] < d2[0]) return dsc ? +1 : -1;
if (d1[0] > d2[0]) return dsc ? -1 : +1;
if (d1[1] < d2[1]) return dsc ? +1 : -1;
return dsc ? -1 : +1;
};
ds.sort(fn);
var newData = [];
for (var i = 0; i < ds.length; ++i)
newData[i] = data[ds[i][1]];
this.data = newData;

if (!suppressEvent) {
this.fireRowsSorted(columnIndex, direction);
}
}

glassy
29 Nov 2006, 7:21 AM
Hmm... here's my version of this. I'm wondering which would be more efficient, or if mine is bad practice. It's just what came to my mind first. The changes from the original code are under the // comments



YAHOO.ext.grid.DefaultDataModel.prototype.sort = function(sortInfo, columnIndex, direction, suppressEvent){
this.sortInfo = sortInfo;
this.sortColumn = columnIndex;
this.sortDir = direction;

// we are going to preserve indexes, so save them first
for (i = 0; i < this.data.length; i++) {
this.data[i].index = i;
}

var dsc = (direction && direction.toUpperCase() == 'DESC');
var sortType = null;
if(sortInfo != null){
if(typeof sortInfo == 'function'){
sortType = sortInfo;
}else if(typeof sortInfo == 'object'){
sortType = sortInfo.getSortType(columnIndex);;
}
}
var fn = function(cells, cells2){
var v1 = sortType ? sortType(cells[columnIndex], cells) : cells[columnIndex];
var v2 = sortType ? sortType(cells2[columnIndex], cells2) : cells2[columnIndex];
if(v1 < v2)
return dsc ? +1 : -1;
if(v1 > v2)
return dsc ? -1 : +1;
// alright, their values are the same, so we use the index to compare
return cells.index - cells2.index;
};
this.data.sort(fn);
if(!suppressEvent){
this.fireRowsSorted(columnIndex, direction);
}
};

glassy
29 Nov 2006, 7:26 AM
Hmm.. the most efficient is probably caching the sortType? check like your last one, but maybe adding it to the data like I did so there is no need for the data assigning loop (if that's possible ... )