如何排序的JavaScript对象的集合,而不将其转换为一个数组(How to sort a col

2019-06-24 12:05发布

我试图避免写我自己的排序算法以下用例:

avatars = {};
avatars[102] = {userInfo: {buddy_name: 'Avatar102', is_online: 1}};
avatars[100] = {userInfo: {buddy_name: 'Avatar100', is_online: 1}};
avatars[101] = {userInfo: {buddy_name: 'Avatar101', is_online: 1}};

console.log(_.keys(avatars));
avatars = _.sortBy(avatars, function(avatar) {return avatar.userInfo.buddy_name.toLowerCase();});
console.log(_.keys(avatars));

这里是控制台输出:

  • [ “102”, “100”, “101”]
  • [ “0”, “1”, “2”]

正如你所看到的,与undescore的sortBy我失去了关键数据。 这个结构可以得到非常大的,所以我尽量避免像转换为数组,然后回收集的东西。 有没有办法做到这一点没有我自己的滚动排序功能?

Answer 1:

你的avatars是不是数组,它只是一个对象:

avatars = {};

所以它的元素没有定义的顺序 :

力学和计数的属性的顺序(步骤6.A在第一算法,步骤7.A在第二)没有被指定。

和15.2.3.7 (和15.2.3.14 ):

如果一个实现定义枚举的特定顺序对换在声明,相同的枚举顺序必须被用于排序在该算法的步骤3中的列表元素。

您还可以查看第8.6节 ,看是否有关于性的对象的顺序任何提及。 为对象属性进行排序的唯一要求是,如果实现定义一个订单的任何地方,然后它到处使用的是相同的顺序,但是这是一个很大的可能 。 大多数的实现可能使用插入顺序为对象的密钥,但我无法找到任何需要他们(我会很感激评论,如果有人能指出在定义对象的按键的任何特定的顺序规格的任何东西)。

这就是说,下划线的sortBy基本上是使用Schwartzian变换结合了标准的JavaScript sort和下划线的pluck解开使用Schwartzian变换备忘录包装; pluck返回一个数组所以sortBy还返回一个数组。 因此,您的最终_.keys(avatars)调用实际上调用_.keys阵列上; 的阵列(AKA枚举的属性)的键阵列的索引,而这些都是从零开始连续的整数。

您使用了错误的数据结构。 如果你需要一个稀疏数组,但还需要操作它就像一个数组(即排序的话),那么你应该把对象中的索引和使用正常的阵列和pluck代替keys

var avatars = [
    {idx: 102, userInfo: {buddy_name: 'Avatar102', is_online: 1}},
    {idx: 100, userInfo: {buddy_name: 'Avatar100', is_online: 1}},
    {idx: 101, userInfo: {buddy_name: 'Avatar101', is_online: 1}}
];
console.log(_(avatars).pluck('idx'));
avatars = _(avatars).sortBy(function(avatar) {
    return avatar.userInfo.buddy_name.toLowerCase();
});
console.log(_(avatars).pluck('idx'));

演示: http://jsfiddle.net/ambiguous/UCWL2/

如果您还需要通过快速访问idx那么你可以设置为直接并联对象idx访问:

var avatars_by_idx = { };
for(var i = 0; i < avatars.length; ++i)
    avatars_by_idx[avatars[i].idx] = avatars[i];

然后avatars_by_idx提供你正在寻找的直接访问。 当然,你必须保持avatarsavatars_by_idx同步的,但如果你隐藏他们两个物体的后面,这不是非常困难。



文章来源: How to sort a collection of objects in JavaScript without converting it to an array