0

生の値と計算された値を含む配列があります。生の値または計算された値のいずれかの結果に基づいて、配列を動的にソートできるようにしたいと考えています。必要となる実際の並べ替えは、実行時までわかりません。

状況と実際の解決策を示す以下のサンプル (plunker here ) をまとめました*。これを改善する方法を知りたいです...具体的には、次の使用:

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 について私が気に入っている点の 1 つは、質問を適切に構成するプロセスによって、(必ずしも でない) 解決策が提示されるまで問題を単純化できることです。プロパティまたは計算された値に基づいて並べ替えることができないというこの問題を開始しました。現在、実装の検証/改善を探しています。

サンプル:

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

    }
}
4

2 に答える 2