如何在Javascript中对哈希表进行排序?

12

我有一个JavaScript哈希表,就像这样:

var things = [ ];
things["hello"] = {"name" : "zzz I fell asleep", "number" : 7};
things["one"] = {"name" : "something", "number" : 18};
things["two"] = {"name" : "another thing", "number" : -2};

我想按名称对它们进行排序,这样如果我遍历哈希表,它们将按顺序排列。

another thing
something
zzz I fell asleep

我尝试过这样做:

function compareThings(thing1, thing2) {
    var name1 = thing1["name"].toLowerCase();
    var name2 = thing2["name"].toLowerCase();
    if (name1 < name2) {
        return -1;
        }
    if (name1 > name2) {
        return 1;
        }
    return 0;
}

things.sort(compareThings);

但它似乎不起作用。

编辑:我想到了,也许排好序的哈希表是一个自相矛盾的说法。如果是这样,那么获取这里的排序列表的最佳方法是什么?


你没有哈希表(也称为对象)或适当的数组。如果你想要一个对象,你应该用 {} 来初始化它,而不是用 []。如果你用 [] 初始化,那么你就有了一个数组,但是不要通过 a["one"]a["two"] 的方式添加元素,而是使用 a.push(...);。只有在你知道你想要什么数据结构之后,才可以考虑排序。(顺便说一句:foo["bar"]foo.bar 是一样的,使用第二种方式,它不会用字符串字面量和大量方括号来混淆代码)。 - user1046334
5个回答

18
如果你想在JavaScript中按顺序迭代哈希表,请创建一个数组,将哈希键填充到数组中,然后进行排序。
<html>
<body>
<pre>
  <script>
    var things = new Object ();
    things["hello"] = {"name" : "zzz I fell asleep", "number" : 7};
    things["one"] = {"name" : "something", "number" : 18};
    things["two"] = {"name" : "another thing", "number" : -2};
    var keys = [];
    for (var key in things) {
      if (things.hasOwnProperty(key)) {
        keys.push(key);
      }
    }
    keys.sort ();
    for (i in keys) {
      var key = keys[i];
      var value = things[key];
      document.write (key +"="+value+"\n");
    }
  </script>
</pre>
</body>
</html>

6
请注意,for...in语句的迭代顺序可能是任意的,在ECMAScript规范中没有描述属性枚举的顺序,这取决于实现... 没有保证,请谨慎使用。 - Christian C. Salvadó
1
@CMS:那我应该使用for (var i = 0; i < keys.length; i++)才是严格正确的吗? - user181548
2
@Kinopiko,确切地说,查看以下文章以获取更多信息:12 - Christian C. Salvadó
1
您也可以使用Object.keys(things)构建keys数组。在循环比较步骤之前,存储数组长度是一个好习惯,因此@CMS上面的for循环可以编写为for (var i = 0, l = keys.length; i < l; i++)。这避免了重复索引keys.length属性的值,而该值并未发生变化。 - Madeline Trotter

7

我的解决方案

things.sort(function(a,b){return a.name - b.name;});

2
OP 没有正确使用数组 things,因此这并没有帮助。 - Felix Kling

5
我开发了一个函数,可以按键对哈希表进行排序,无论值是数字还是字符串。如果表是关联表,则保留键。
function sortHashTableByKey(hash, key_order, remove_key)
{
    var tmp = [],
        end = [],
        f_order = null;
    remove_key = remove_key || false;
    for (var key in hash)
    {
        if (hash.hasOwnProperty(key))
        {
            tmp.push(hash[key][key_order]);
        }
    }
    if (hash && hash[0] && typeof(hash[0][key_order]) === 'number')
    {
        f_order = function (a, b) { return a - b; };
    }
    tmp.sort(f_order);
    function getHash(hash, value)
    {
        for (k in hash)
        {
            if (hash[k] && hash[k][key_order] === value)
            {
                return { key : k, hash : hash[k] };
            }
        }
    }
    for (var i = 0, l = tmp.length; i < l; i++)
    {
        tmp[i] = getHash(hash, tmp[i]);
        if (remove_key)
        {
            delete tmp[i].hash[key_order];
        }
        if (!hash.length)
        {
            end[tmp[i].key] = tmp[i].hash;
        }
        else
        {
            end.push(tmp[i].hash);
        }
    }
    return end;
}

这将会做到:
var things = new Object ();
things["hello"] = {"name" : "zzz I fell asleep", "number" : 7};
things["one"] = {"name" : "something", "number" : 18};
things["two"] = {"name" : "another thing", "number" : -2};

things = sortHashTableByKey(things, 'name');

/*
[
  two: { name: 'another thing', number: -2 },
  one: { name: 'something', number: 18 },
  hello: { name: 'zzz I fell asleep', number: 7 }
]
*/

@HaykSaakian,函数的进展如何?作为一个人类,我真的很钦佩任何人在超越心灵/身体问题方面维持状态和功能的努力。太棒了。 - deepelement
我应该说“做这个”而不是“成为这个” @ToddMorrison - Hayk Saakian

2

您的参数是thing1thing2,但您正在引用一些称为asp1asp2的变量,根据您提供的源代码,我认为这些变量不存在。

此外,我认为您要寻找的是关联数组,它不是用[]语法实例化的。有关更多信息,请参见此处:

http://www.quirksmode.org/js/associative.html

编辑:我认为在JavaScript中没有一个数组能够让您做到想要的。

您可以拥有普通的数组,它将允许您进行自定义排序,或者您可以拥有关联数组,它将允许您具有命名值。

对于常规数组,您显然可以迭代索引。

使用关联数组,您可以通过执行for (var key in myArray)迭代名称。


1
小心使用for...in语法。它会循环遍历对象所有的属性,其中包括不只是数组键。 - Syntactic
这是正确的,但只要它不继承自任何东西,就不应该成为问题。 - Daniel Schaffer

0

和 eeerahul 一样,使用 keys() 和 String().localeCompare():

function sort_by_key(t_kv,v_kv){
  return(Object.keys(t_kv).sort(
    function(a,b){return(
      String(t_kv[a][v_kv]).localeCompare(String(t_kv[b][v_kv])))}))
}

t={two:{s:'two',n:2},three:{s:'three',n:3},one:{s:'one',n:1}}
sort_by_key(t,'n')
    ["one", "two", "three"]
sort_by_key(t,'s')
    ["one", "three", "two"]    

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