JavaScript中通过任意列表对对象数组进行排序

23

给定一个类似这样的对象数组:

objects = [
  { id: 'aaaa', description: 'foo' },
  { id: 'bbbb', description: 'bar' },
  { id: 'cccc', description: 'baz' }
];

并且一个像这样的字符串数组:

order = [ 'bbbb', 'aaaa', 'cccc' ];

我该如何对第一个数组进行排序,以便id属性与第二个数组的顺序匹配?


2
当任何列表中缺少元素时,应该发生什么? - Kroltan
3个回答

43

试试这个:

objects.sort(function(a, b){
    return order.indexOf(a.id) - order.indexOf(b.id)
});

假设变量与您在问题中声明的变量相同,则应返回:

[
    { id: 'bbbb', description: 'bar' },
    { id: 'aaaa', description: 'foo' },
    { id: 'cccc', description: 'baz' }
];

(它实际上修改了objects变量)


如果objects中有一些元素不在orders数组中,它们将出现在顶部。有没有办法让它们出现在列表的末尾而不是开头? - Barry Michael Doyle
@BarryMichaelDoyle:是的,你需要检查indexOf的两个值是否都为-1,如果它们确实都是-1,则返回Number.MAX_VALUE - Cerbrus

2

您需要一种将字符串转换为数组位置的方法,即数组的索引函数。

新版浏览器中已经有了这个函数,但为了向后兼容,如果没有该函数,则需要添加它:

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(str) {
    var i;
    for (i = 0; i < this.length; i++) if (this[i] == str) return i;
    return -1;
  }
}

现在,您可以通过将字符串转换为索引来对数组进行排序:
objects.sort(function(x,y){ return order.indexOf(x.id) - order.indexOf(y.id); });

示例: http://jsfiddle.net/Guffa/u3CQW/


0
使用映射对象可以实现(几乎)恒定的访问时间。
/* Create a mapping object `orderIndex`:
{
  "bbbb": 0,
  "aaaa": 1,
  "cccc": 2
}
*/
const orderIndex = {}
order.forEach((value, index) => orderIndex[value] = index);

// Sort
objects.sort((a, b) => orderIndex[a.id] - orderIndex[b.id]);

// data
const objects = [
  { id: 'aaaa', description: 'foo' },
  { id: 'bbbb', description: 'bar' },
  { id: 'cccc', description: 'baz' }
];
const order = [ 'bbbb', 'aaaa', 'cccc' ];

/* Create a mapping object `orderIndex`:
{
  "bbbb": 0,
  "aaaa": 1,
  "cccc": 2
}
*/
const orderIndex = {}
order.forEach((value, index) => orderIndex[value] = index);

// Sort
objects.sort((a, b) => orderIndex[a.id] - orderIndex[b.id]);

// Log
console.log('orderIndex:', orderIndex);
console.log('objects:', objects);


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