簡體   English   中英

JavaScript在Chrome中按乘法字段對對象進行數組排序

[英]JavaScript Sort Array of Objects by Multipe Fields in Chrome

話雖如此,聽起來很簡單,但是我沒有成功在Chrome中達到完美的效果(我在IE中做到了)

所以我有一個對象:

var objs=[
{ name: "water", type: "cold" },
{ name: "tea", type: "hot" },
{ name: "coffee", type: "hot" },
{ name: "choco", type: "cold" }
];

我按名稱對其進行了升序排列,並得到了預期的結果:

  1. 巧克力,冷
  2. 熱咖啡
  3. 茶,熱
  4. 水,冷

我在IE和Chrome上都得到了相同的結果,

然后,我再次按類型,升序和期望對它進行排序:

  1. 巧克力,冷
  2. 水,冷
  3. 熱咖啡
  4. 茶,熱

但是我只在IE中獲得了預期的結果,而在Chrome中,結果幾乎是相同的,只是“水”位於頂部(它破壞了第一次排序)

任何一般的方法想法? (我需要在每個字段中保持一個函數調用,而不是同時在一個函數中按多個字段進行排序)

我的排序方法是這樣的:

function SortBy(key,Asc,method){
  var GetKey=function(x) {return method ? method(x[key]) : x[key] };
  return function(a,b){
    var A=GetKey(a), B=GetKey(b);
    return ((A<B) ? -1 : ((A>B) ? 1 : 0)) * [-1,1][+!!Asc];
  }
}

var sortedObjects=Clone(objs); //clone the current objs

sortedObjects.sort(SortBy("name" , true, function(x){
  if (typeof(x)=="string") return x.toLowerCase(); else return x;
}));

objs=sortedObjects; //got the first result

sortedObjects.sort(SortBy("type",true,function(x){
  if (typeof(x)=="string") return x.toLowerCase(); else return x;
}));

objs=sortedObjects;

此處編輯的是小提琴(問題是“水”): DEMO

如果我們閱讀ES5規范 §15.4.4.11Array.prototype.sort ,則第二句話指出

排序不一定是穩定的(也就是說,比較相等的元素不一定保持其原始順序)

也就是說,在JavaScript中 ,如果比較器說兩件事相等(給出0 ),則它們是否被交換並不重要,因此,在某些環境中,它們可能由於其他原因(例如哈希)而被交換或只是實施。

即,您所體驗到的結果是規范定義的有效sort結果,並且每次重復相同的sort甚至可能會得出不同的結果


希望我不會對此感到失望,但是如果您將其作為一個函數來完成,則無需遍歷數組多次,並且可以避免意外的結果

/*  list = multiSort(list [, obj, ...])
 *  where e.g. obj = {
 *      key: "keyToLookAt",
 *      optional comparator: function (a, b) {return a<b || ((a===b)-1);},
 *      optional ascending: default true
 *  }
*/

var multiSort = (function () {
    function generateSorter(key, comparator, ascending) {
        ascending = 2 * !!ascending - 1;
        if (comparator) {
            return function sorter(a, b) {
                return ascending * comparator(a[key], b[key]);
            };
        }
        return function sorter(a, b) {
            a = a[key];
            b = b[key];
            return ascending * (a < b ? -1 : a > b ? 1 : 0);
        };
    }
    function sortManager(sorters) {
        return function (a, b) {
            var ret, i = 0;
            for (; i < sorters.length; ++i) {
                ret = sorters[i](a, b);
                if (ret !== 0) return ret;
            }
            return 0;
        };
    }
    function multiSort(list) {
        var i = 1, sorters = [];
        for (; i < arguments.length; ++i) {
            sorters.push(generateSorter(
                arguments[i].key,
                arguments[i].comparator,
                'ascending' in arguments[i] ? arguments[i].ascending : 1
            ));
        }
        list.sort(sortManager(sorters));
        return list;
    }
    return multiSort;
}());

然后在使用它時,“最嚴格”的排序規則首先出現

multiSort(
    [
        { name: "water", type: "cold" },
        { name: "tea", type: "hot" },
        { name: "coffee", type: "hot" },
        { name: "choco", type: "cold" }
    ],
    {key: 'type'},
    {key: 'name'}
);
/*
[
    { "name": "choco" , "type": "cold" },
    { "name": "water" , "type": "cold" },
    { "name": "coffee", "type": "hot" },
    { "name": "tea"   , "type": "hot" }
]
*/

我創建了一個CodePen來測試和正常工作...我用更易讀的代碼編寫了相同的想法

function SortBy(key, isAsc, fn){
     fn = fn || function (x){ return x; };

    return function(objA, objB){
       var a = fn(objA[key]);
       var b = fn(objB[key]);

       var isGreater = isAsc ? 1 : -1;
       var isLesser = -isGreater;
       var isSame = 0;

       if( a > b ) return isGreater;
       if( a == b ) return isSame;
       if( a < b ) return isLesser;
       return -1; //to down the undefined

     }  

}

http://codepen.io/anon/pen/sGgDq編輯並測試了大量數據

ps:我使用了codepen,因為jsfiddle無法在我的工作中打開

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM