通过字符串对包含数组的数组进行排序

65

我有一个包含多个数组的数组,我想根据这些数组中的某个字符串对这些数组进行排序。

var myArray = [
                [1, 'alfred', '...'],
                [23, 'berta', '...'],
                [2, 'zimmermann', '...'],
                [4, 'albert', '...'],
              ];

如何按名称对它进行排序,以便 albert 排在第一位, zimmermann 排在最后?

如果可以使用整数进行排序,我知道该如何做,但使用字符串却使我不知所措。

感谢您的帮助!:)


2
这与https://dev59.com/e3E95IYBdhLWcg3wdtqj相似(尽管不是重复的)。那个问题的被接受的答案应该会对你有所帮助。 - Lightness Races in Orbit
6个回答

105

可以通过将支持函数作为参数传递给Array.sort方法调用来实现。

就像这样:

 function Comparator(a, b) {
   if (a[1] < b[1]) return -1;
   if (a[1] > b[1]) return 1;
   return 0;
 }

 var myArray = [
   [1, 'alfred', '...'],
   [23, 'berta', '...'],
   [2, 'zimmermann', '...'],
   [4, 'albert', '...'],
 ];

 myArray = myArray.sort(Comparator);
 console.log(myArray);


谢谢Martin,这个很好用。但是我有一个问题,那些小写字母开头的名字和以同样大写字母开头的名字排序不一样。 - dmnkhhn
3
在这种情况下,可以在Comparator方法中使用字符串的toUpperCase方法(a[1].toUpperCase()和b[1].toUpperCase()),这将使排序不区分大小写。 - Martin Milan
虽然有些 OT,但在许多编程语言中(如Perl、Ruby、PHP等),都有一个“太空船运算符”,它可以本地比较并返回-1、0或1(根据您的比较器方法)。考虑到ES经常借鉴其他语言的想法,我预计它很快就会出现在Babel中。 - SamGoody

41

您仍然可以使用array.sort()与自定义函数。在函数内部,只需比较您要用作键的元素即可。对于您的示例,您可以使用:

myArray.sort(function(a, b) { 
    return a[1] > b[1] ? 1 : -1;
});

我认为你忘记了 return - wong2
这个代码无法处理相等的字符串(即不会返回-1、1或0)。@Martin Milan的回答更好。 - Aleadam
1
@Aleadam 从理论上讲,你是正确的。比较器不符合要求的规格。然而,在实践中,如果您不关心在排序算法期间交换具有相等键的元素,则这个解决方案足够好。对于大型数组,这种解决方案可能会变得更慢 - 这取决于array.sort()的实现方式。但至少我需要返回1或-1。正在编辑答案。 - vhallac
2
如果需要保留相等的元素位置,则返回:return a[1] == b[1] ? 0 : (a[1] > b[1] ? 1 : -1); - gordon

15

无法在对象中找到函数localeCompare。 - user776942
你的数组元素必须是字符串,而不是对象。 - andyrandy
是的,我已经尝试将数字转换为字符串,但仍然得到混乱的结果。http://stackoverflow.com/questions/33004116/how-do-i-pre-sort-numbers-and-not-screw-up-the-formatting - user776942

9
在ES6中,人们可能会使用相对简短的方式来表达:
myArray.sort(([a], [b]) => a.localeCompare(b))

或者

myArray.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)

有用/现代的部分是 => lambda 运算符和 [X] 参数解构。

7

太棒了!在这个例子中,按照第一个元素、第二个元素和第三个元素进行复合排序,都是升序的。

myArray=myArray.sort(function(a,b){
    retVal=0;
    if(a[0]!=b[0]) retVal=a[0]>b[0]?1:-1;
    else if(a[1]!=b[1]) retVal=a[1]>b[1]?1:-1;
    else if(a[2]!=b[2]) retVal=a[2]>b[2]?1:-1;
    return retVal
});

(多个列上的多重排序)


1
这个能根据数组长度动态完成吗? - gjonte
我还没有使用动态数组长度,但我会朝着这个方向前进:retVal=0; var lenA=a.length; var lenB=b.length; var toLen=Math.min(lenA,lenB); for(i=0;i<toLen;i++){if(a[i]!=b[i]) retVal=a[i]>b[i]?1:-1;} return retVal;(ps 很抱歉这么久没回复。) - gordon
这假设您的数组元素排序与比较元素的层次结构相匹配。如果您需要在元素之间反弹比较,我想您可以尝试将该顺序作为另一个参数传递进去。 - gordon

0
一直遇到这里发布的解决方案问题。对于一个简单的数组内简单字符串的排序器,我使用了以下代码:
arr = ["aaa","abc","aba"]
arr.sort((a, b) => a.localeCompare(b));
console.log(arr);
//['aaa','aba','abc']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接