Javascript排序功能。按First排序,然后按Second排序

时间:2012-02-07 11:16:50

标签: javascript arrays sorting

我有一个要排序的对象数组。每个对象都有两个参数:强度和名称

objects = []
object[0] = {strength: 3, name: "Leo"}
object[1] = {strength: 3, name: "Mike"}

我想首先按强度排序,然后按名称按字母顺序排序。我使用以下代码按第一个参数排序。我如何排序呢?

function sortF(ob1,ob2) {
  if (ob1.strength > ob2.strength) {return 1}
  else if (ob1.strength < ob2.strength){return -1}
  return 0;
};

感谢您的帮助。

11 个答案:

答案 0 :(得分:70)

将排序功能扩展为这样;

function sortF(ob1,ob2) {
    if (ob1.strength > ob2.strength) {
        return 1;
    } else if (ob1.strength < ob2.strength) { 
        return -1;
    }

    // Else go to the 2nd item
    if (ob1.name < ob2.name) { 
        return -1;
    } else if (ob1.name > ob2.name) {
        return 1
    } else { // nothing to split them
        return 0;
    }
}

字符串<>比较是字母比较。

答案 1 :(得分:43)

当按多个键排序时,这个小功能通常很方便:

cmp = function(a, b) {
    if (a > b) return +1;
    if (a < b) return -1;
    return 0;
}

或者更简洁地说,

cmp = (a, b) => (a > b) - (a < b)

像这样申请:

array.sort(function(a, b) { 
    return cmp(a.strength,b.strength) || cmp(a.name,b.name)
})

Javascript确实缺少Ruby的spaceship operator,这使得这种比较非常优雅。

答案 2 :(得分:20)

您可以使用逻辑OR链接排序顺序。

objects.sort(function (a, b) {
    return a.strength - b.strength || a.name.localeCompare(b.name);
});

答案 3 :(得分:6)

当我在寻找这个问题的答案时,我在StackOverflow上找到的答案并不是我所希望的。所以我创建了一个简单,可重用的函数来完成这个。它允许您使用标准的Array.sort,但使用firstBy()。thenBy()。thenBy()样式。 https://github.com/Teun/thenBy.js

PS。这是我第二次发布这个。主持人第一次删除了“请不要为自己的工作制作宣传帖子”。我不确定这里的规则是什么,但我试图回答这个问题。我很抱歉这是我自己的工作。请随意删除,但请指出我当时的规则。

答案 4 :(得分:1)

function sortF(ob1,ob2) {
  if (ob1.strength > ob2.strength) {return 1}
  else if (ob1.strength < ob2.strength) {return -1}
  else if (ob1.name > ob2.name) {return 1}
  return -1;
};

编辑:按强度排序,如果强度相等,则按名称排序。 在两个对象中强度和名称相等的情况不需要单独计算,因为-1的最终返回表示关系小于或等于。排序的结果是正确的。它可能会让它运行得更快或更慢,我不知道。如果你想要明确,只需替换

return -1;

else if (ob1.name < ob2.name) {return -1}
return 0;

答案 5 :(得分:0)

在下面找到'sortFn'功能。此函数按无限数量的参数排序(例如在c#:SortBy(...)。ThenBy(...)。ThenByDesc(...))。

function sortFn() {
    var sortByProps = Array.prototype.slice.call(arguments),
        cmpFn = function(left, right, sortOrder) {
            var sortMultiplier = sortOrder === "asc" ? 1 : -1;

            if (left > right) {
                return +1 * sortMultiplier;
            }
            if (left < right) {
                return -1 * sortMultiplier;
            }
            return 0;
        };


    return function(sortLeft, sortRight) {
        // get value from object by complex key
        var getValueByStr = function(obj, path) {
            var i, len;

            //prepare keys
            path = path.replace('[', '.');
            path = path.replace(']', '');
            path = path.split('.');

            len = path.length;

            for (i = 0; i < len; i++) {
                if (!obj || typeof obj !== 'object') {
                    return obj;
                }
                obj = obj[path[i]];
            }

            return obj;
        };

        return sortByProps.map(function(property) {
            return cmpFn(getValueByStr(sortLeft, property.prop), getValueByStr(sortRight, property.prop), property.sortOrder);
        }).reduceRight(function(left, right) {
            return right || left;
        });
    };
}

var arr = [{
    name: 'marry',
    LocalizedData: {
        'en-US': {
            Value: 10000
        }
    }
}, {
    name: 'larry',
    LocalizedData: {
        'en-US': {
            Value: 2
        }
    }
}, {
    name: 'marry',
    LocalizedData: {
        'en-US': {
            Value: 100
        }
    }
}, {
    name: 'larry',
    LocalizedData: {
        'en-US': {
            Value: 1
        }
    }
}];
document.getElementsByTagName('pre')[0].innerText = JSON.stringify(arr)

arr.sort(sortFn({
    prop: "name",
    sortOrder: "asc"
}, {
    prop: "LocalizedData[en-US].Value",
    sortOrder: "desc"
}));

document.getElementsByTagName('pre')[1].innerText = JSON.stringify(arr)
pre {
    font-family: "Courier New" Courier monospace;
    white-space: pre-wrap;
}
Before:
<pre></pre>
Result:
<pre></pre>

答案 6 :(得分:0)

使用ES6,你可以做到

array.sort(function(a, b) { 
 return SortFn(a.strength,b.strength) || SortFn(a.name,b.name)
})

 private sortFn(a, b): number {
    return a === b ? 0 : a < b ? -1 : 1;
}

答案 7 :(得分:0)

史蒂夫的答案,但是更漂亮。

objects.sort(function(a,b)
{
  if(a.strength > b.strength) {return  1;}
  if(a.strength < b.strength) {return -1;}
  if(a.name     > b.name    ) {return  1;}
  if(a.name     < b.name    ) {return -1;}
  return 0;
}

答案 8 :(得分:0)

这是我使用的函数。它会做任意数字。

function Sorter(){
  
  var self = this;
  this.sortDefs = [];
  
  for (let i = 0; i < arguments.length; i++) {
  // Runs 5 times, with values of step 0 through 4.
    this.sortDefs.push(arguments[i]);
  }
  
  this.sort = function(a, b){
  
    for (let i = 0; i < self.sortDefs.length; i++) {

        if (a[self.sortDefs[i]] < b[self.sortDefs[i]]) { 
          return -1;
        } else if (a[self.sortDefs[i]] > b[self.sortDefs[i]]) {
          return 1
        }
    }
    
    return 0;
  }
}

data.sort(new Sorter('category','name').sort);

答案 9 :(得分:-1)

在2018年,您可以仅使用sort()ES6函数,该函数可以准确地完成您想要的。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

答案 10 :(得分:-1)

一个长而有力的内衬怎么样?

const orderByMultipleFactory = (fields) => (a, b) => fields.reduce((acc, {name, asc = true, compareFn}) => acc || (compareFn ? compareFn(a, b) : (isString(a[name]) ? (asc ? a[name].localeCompare(b[name]) : b[name].localeCompare(a[name])) : (asc ? a[name] - b[name] : b[name] - a[name]))), 0);

Fields是具有name字段的对象数组,该字段指定对象的属性,然后是可选的asccompareFn以控制方向或覆盖默认的比较方法。
默认情况下,字符串将通过localCompare与其他所有字符串进行比较,并通过简单的a - b进行比较。

示例:

[{a: 2, b: 'y'}, {a: 3, b: 'x'}, {a: 2, b: 'z'}]
  .sort(orderByMultipleFactory([{name: 'a', asc: false}, {name: 'b'}]))
// result is sorted by "a" descending and equal records by "b" ascending.