JavaScript在Chrome中通过多个字段对对象数组进行排序

JavaScript在Chrome中通过多个字段对对象数组进行排序,javascript,google-chrome,sorting,Javascript,Google Chrome,Sorting,从它所说的,这听起来很简单,但我没有成功地在Chrome上实现完美的效果(我是在IE上实现的) 所以我有一个目标: var objs=[ { name: "water", type: "cold" }, { name: "tea", type: "hot" }, { name: "coffee", type: "hot" }, { name: "choco", type: "cold" } ]; 我按名称升序排序,得到了预期结果: 巧克力,冷的 热咖啡 茶,热的 冷水 我在IE和Chrome上

从它所说的,这听起来很简单,但我没有成功地在Chrome上实现完美的效果(我是在IE上实现的)

所以我有一个目标:

var objs=[
{ name: "water", type: "cold" },
{ name: "tea", type: "hot" },
{ name: "coffee", type: "hot" },
{ name: "choco", type: "cold" }
];
我按名称升序排序,得到了预期结果:

  • 巧克力,冷的
  • 热咖啡
  • 茶,热的
  • 冷水
  • 我在IE和Chrome上都得到了相同的结果

    然后,我再次按类型、升序和我的期望对其进行排序:

  • 巧克力,冷的
  • 冷水
  • 热咖啡
  • 茶,热的
  • 但我在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;
    
    功能排序(键、Asc、方法){
    var GetKey=function(x){returnmethod?method(x[key]):x[key]};
    返回函数(a,b){
    变量A=GetKey(A),B=GetKey(B);
    返回((AB)?1:0))*[-1,1][+!!Asc];
    }
    }
    var sortedObjects=克隆(objs)//克隆当前对象
    sortedObjects.sort(排序方式(“名称”),true,function(x){
    if(typeof(x)=“string”)返回x.toLowerCase();else返回x;
    }));
    objs=分类对象//得到第一个结果
    sortedObjects.sort(排序方式(“类型”),true,function(x){
    if(typeof(x)=“string”)返回x.toLowerCase();else返回x;
    }));
    objs=分类对象;
    
    编辑这里是小提琴(问题是“水”):

    如果我们阅读ES5规范,第二句话会说

    排序不一定是稳定的(即,比较相等的元素不一定保持其原始顺序)

    也就是说,在JavaScript中,如果比较器说两件事是相等的(通过给出
    0
    ),那么它们是否被交换并不重要,因此在某些环境中,它们可能会由于其他原因而被交换,例如它们的哈希或只是实现

    i、 e.您体验到的结果是规范定义的
    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;
    }());
    

    我创建了一个代码笔来测试和工作良好。。。 我用可读性更强的代码写了同样的想法

    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
    
         }  
    
    }
    
    功能排序(键、isAsc、fn){
    fn=fn | |函数(x){返回x;};
    返回函数(objA、objB){
    var a=fn(objA[关键]);
    var b=fn(objB[关键]);
    var Ismorer=isAsc?1:-1;
    var isLesser=-ismore;
    var IsName=0;
    如果(a>b)返回值更大;
    如果(a==b),返回ISNAME;
    如果(a
    用大量数据编辑和测试


    p、 s:我使用codepen是因为JSFIDLE在我的工作中没有打开

    你能创建一个小提琴吗?这在google chrome中对我很有用。你可以发布一个JSFIDLE或其他东西吗?为什么
    需要为每个字段保留一个函数调用?这种低效我会创建一个提琴,显然它是有效的(我使用了样本数据),如果我使用更多的数据,那么它将不起作用您期望的结果不是您根据规范可以假设的结果,请查看对我答案的最后一次编辑显然我的样本数据只有4个数据它工作正常,我在提琴中获得了更多数据,在chrome中排序时出现错误。请发送小提琴:D,对我来说,处理大量数据效果很好,如果我发现问题,我会修复。如果在chrome和IE中打开它,输出会有所不同(我希望结果与IE中的一样)
    
    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
    
         }  
    
    }