首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对JavaScript中的对象集合进行排序,而不将其转换为数组

如何对JavaScript中的对象集合进行排序,而不将其转换为数组
EN

Stack Overflow用户
提问于 2012-05-16 17:18:59
回答 1查看 21K关注 0票数 12

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

代码语言:javascript
复制
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,我正在丢失关键数据。这个结构可以变得非常大,所以我试图避免像转换到数组然后返回到集合这样的事情。有没有办法做到这一点,而不滚动我自己的排序功能?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-16 18:33:54

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

代码语言:javascript
复制
avatars = {};

所以有no defined order for its elements

未指定枚举属性的机制和顺序(第一种算法中的步骤6.a,第二种算法中的步骤7.a )。

15.2.3.7 (和15.2.3.14):

如果实现为for-in语句定义了特定的枚举顺序,则必须使用相同的枚举顺序对此算法的步骤3中的列表元素进行排序。

您还可以检查section 8.6,看看是否提到了对象中的属性顺序。对象属性排序的唯一要求是,如果实现在任何地方定义一个顺序,那么它必须在任何地方使用相同的顺序,但这是一个很大的假设。大多数实现可能对对象的键使用插入顺序,但我找不到需要它们的任何东西(如果有人能指出规范中定义对象键的任何特定顺序的任何内容,我将非常感激)。

也就是说,下划线的sortBy基本上是一个与标准的JavaScript sort和下划线的pluck相结合的Schwartzian Transform,用于解开Schwartzian转换备忘录包装器;pluck返回数组,sortBy也返回数组。因此,最后的_.keys(avatars)调用实际上是在数组上调用_.keys;数组(AKA可枚举属性)的键是数组的索引,它们是从零开始的连续整数。

你使用了错误的数据结构。如果需要稀疏数组,但也需要像数组一样对其进行操作(即排序),则应该将索引放在对象中,使用普通数组和pluck,而不是keys

代码语言:javascript
复制
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访问:

代码语言:javascript
复制
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保持同步,但如果将它们都隐藏在对象后面,这并不是非常困难。

票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10623463

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档