我有一个包含原始值和计算值的数组。我希望能够根据原始值或计算值之一的结果对数组进行动态排序。直到运行时才会知道所需的实际排序。
我汇总了以下示例(此处为 plunker ),演示了情况和可行的解决方案*。我想知道如何改进这个......特别是使用:
Array.prototype.sortBy = function (property) {
return this.sort(mySort(property));
};
是从这个stackoverflow 响应中复制而来的——Ege Özcan 特别指出
//Please don't just copy-paste this code.
//See the explanation at the end. A lot could break.
我想了解如何在我的对象上实现这种排序算法而不违反“很多可能会破坏”警告(我不明白)。
*我喜欢stackoverflow的一件事是,很好地构建问题的过程经常会导致您将问题简化到(不一定是)解决方案出现的程度。我开始这个问题无法根据属性或计算值进行排序。现在,我正在寻找对实施的验证/改进。
样品:
var rawData = [
{ "Id": 3, "itemCount": 3531, "val1": 905, "val2": 172 },
{ "Id": 2, "itemCount": 3111, "val1": 799, "val2": 147 },
{ "Id": 4, "itemCount": 3411, "val1": 871, "val2": 199 },
{ "Id": 5, "itemCount": 3414, "val1": 892, "val2": 178 },
{ "Id": 1, "itemCount": 3182, "val1": 845, "val2": 155 }
];
function MyItem(item) {
var self = this;
for (var val in item) {
if (item.hasOwnProperty(val)) {
self[val] = item[val];
}
}
}
function extendMyItems() {
MyItem.prototype.computedOne = function () {
var input = this;
return input.itemCount / input.val1;
};
MyItem.prototype.computedTwo = function () {
var input = this;
return input.val1 * input.val2;
};
}
function getItems(input) {
var ret = [];
for (var i = 0; i < input.length; i++) {
var item = new MyItem(input[i]);
ret.push(item);
}
return ret;
}
function doIt() {
Array.prototype.sortBy = function (property) {
return this.sort(mySort(property));
};
extendMyItems();
var sortList = [{ "sortKey": "Id", "sortOrder": "asc" },
{ "sortKey": "val1", "sortOrder": "asc" },
{ "sortKey": "val2", "sortOrder": "desc" },
{ "sortKey": "computedOne", "sortOrder": "desc", "isComputed": true },
{ "sortKey": "Id", "sortOrder": "desc" },
{ "sortKey": "computedTwo", "sortOrder": "asc", "isComputed": true }];
// get the array of MyItem
var myItems = getItems(rawData);
for (var k = 0; k < sortList.length; k++) {
myItems.sortBy(sortList[k]);
// process the sorted items here (ranking/scoring, etc)
for (var p = 0; p < myItems.length; p++) {
console.log('Id: ' + myItems[p].Id + ' val1: ' + myItems[p].val1 + ' val2: ' + myItems[p].val2 + ' c1: ' + myItems[p].computedOne() + ' c2: ' + myItems[p].computedTwo());
}
}
function mySort(srt) {
var so = srt.sortOrder == 'asc' ? 1 : -1;
var key = srt.sortKey;
var result = 0;
console.log(srt.sortKey + ' ' + srt.sortOrder + ':');
return function (a, b) {
if (srt.isComputed) {
// this seems like a hack - is there a better way to switch between property and function value????
result = (a[key]() < b[key]()) ? -1 : (a[key]() > b[key]()) ? 1 : 0;
} else {
result = (a[key] < b[key]) ? -1 : (a[key] > b[key]) ? 1 : 0;
}
return result * so;
};
}
}