简体   繁体   English

以排序的顺序遍历Javascript关联数组

[英]Iterate over a Javascript associative array in sorted order

Let's say I have a Javascript associative array (aka hash, aka dictionary): 假设我有一个Javascript关联数组(又名哈希,又名字典):

var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;

How can I iterate over the keys in sorted order? 如何按排序顺序遍历键? If it helps simplify things, I don't even need the values (they're all just the number 1). 如果它有助于简化操作,我什至不需要这些值(它们全都是数字1)。

You can use the Object.keys built-in method: 您可以使用Object.keys内置方法:

var sorted_keys = Object.keys(a).sort()

(Note: this does not work in very old browsers not supporting EcmaScript5, notably IE6, 7 and 8. For detailed up-to-date statistics, see this table ) (注意:这在不支持EcmaScript5的非常旧的浏览器中不起作用,尤其是IE6、7和8。有关最新统计信息,请参见此

You cannot iterate over them directly, but you can find all the keys and then just sort them. 您不能直接对其进行迭代,但是可以找到所有键,然后对其进行排序。

var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;    

function keys(obj)
{
    var keys = [];

    for(var key in obj)
    {
        if(obj.hasOwnProperty(key))
        {
            keys.push(key);
        }
    }

    return keys;
}

keys(a).sort(); // ["a", "b", "z"]

However there is no need to make the variable 'a' an array. 但是,无需将变量“ a”设置为数组。 You are really just using it as an object and should create it like this: 您实际上只是将其用作对象,应该这样创建它:

var a = {};
a["key"] = "value";

you could even prototype it onto object: 您甚至可以将其原型化到对象上:

Object.prototype.iterateSorted = function(worker)
{
    var keys = [];
    for (var key in this)
    {
        if (this.hasOwnProperty(key))
            keys.push(key);
    }
    keys.sort();

    for (var i = 0; i < keys.length; i++)
    {
        worker(this[ keys[i] ]);
    }
}

and the usage: 和用法:

var myObj = { a:1, b:2 };
myObj.iterateSorted(function(value)
{
    alert(value);
} 

I agree with Swingley's answer , and I think it is an important point a lot of these more elaborate solutions are missing. 我同意Swingley的回答 ,并且我认为重要的一点是缺少许多这些更详尽的解决方案。 If you are only concerned with the keys in the associative array and all the values are '1', then simply store the 'keys' as values in an array. 如果仅关注关联数组中的键,并且所有值均为“ 1”,则只需将“键”作为值存储在数组中。

Instead of: 代替:

var a = { b:1, z:1, a:1 };
// relatively elaborate code to retrieve the keys and sort them

Use: 采用:

var a = [ 'b', 'z', 'a' ];
alert(a.sort());

The one drawback to this is that you can not determine whether a specific key is set as easily. 这样做的一个缺点是,您无法确定是否轻松设置了特定键。 See this answer to javascript function inArray for an answer to that problem. 有关此问题的答案 ,请参见javascript函数inArray的答案。 One issue with the solution presented is that a.hasValue('key') is going to be slightly slower than a['key'] . 提出的解决方案的一个问题是a.hasValue('key')将比a['key']稍微慢一些。 That may or may not matter in your code. 这可能与您的代码无关紧要。

There's no concise way to directly manipulate the "keys" of a Javascript object. 没有简洁的方法可以直接操作Javascript对象的“键”。 It's not really designed for that. 它不是真的为此设计的。 Do you have the freedom to put your data in something better than a regular object (or an Array, as your sample code suggests)? 您是否有自由将数据放在比常规对象(或示例代码所建议的数组)更好的数据中?

If so, and if your question could be rephrased as "What dictionary-like object should I use if I want to iterate over the keys in sorted order?" 如果是这样,并且您的问题可以改写为“如果要按排序顺序遍历键,应该使用哪个类似于字典的对象?” then you might develop an object like this: 那么您可以开发一个像这样的对象:

var a = {
  keys : new Array(),
  hash : new Object(),
  set : function(key, value) {
    if (typeof(this.hash[key]) == "undefined") { this.keys.push(key); }
    this.hash[key] = value;
  },
  get : function(key) {
    return this.hash[key];
  },
  getSortedKeys : function() {
    this.keys.sort();
    return this.keys;
  }
};

// sample use
a.set('b',1);
a.set('z',1);
a.set('a',1);
var sortedKeys = a.getSortedKeys();
for (var i in sortedKeys) { print(sortedKeys[i]); }

If you have no control over the fact that the data is in a regular object, this utility would convert the regular object to your fully-functional dictionary: 如果您无法控制数据在常规对象中的事实,则此实用程序会将常规对象转换为功能齐全的字典:

a.importObject = function(object) {
  for (var i in object) { this.set(i, object); }
};

This was a object definition (instead of a reusable constructor function) for simplicity; 为了简单起见,这是一个对象定义(而不是可重用的构造函数)。 edit at will. 随意编辑。

You can use the keys function from the underscore.js library to get the keys, then the sort() array method to sort them: 您可以使用keys功能从underscore.js库拿到钥匙,然后sort()阵列方法来对它们进行排序:

var sortedKeys = _.keys(dict).sort();

The keys function in the underscore's source code: keys的功能在下划线的源代码:

// Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = nativeKeys || function(obj) {
    if (obj !== Object(obj)) throw new TypeError('Invalid object');
    var keys = [];
    for (var key in obj) if (_.has(obj, key)) keys.push(key);
    return keys;
};    

// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_.has = function(obj, key) {
    return hasOwnProperty.call(obj, key);
};

Get the keys in the first for loop, sort it, use the sorted result in the 2nd for loop. 在第一个for循环中获取键,对其for排序,然后在第二个for循环中使用排序后的结果。

var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;

var b = [];
for (k in a) b.push(k);
b.sort();
for (var i = 0; i < b.length; ++i) alert(b[i]);

 var a = new Array(); a['b'] = 1; a['z'] = 1; a['a'] = 1; var keys=Object.keys(a).sort(); for(var i=0,key=keys[0];i<keys.length;key=keys[++i]){ document.write(key+' : '+a[key]+'<br>'); } 

I really like @luke-schafer's prototype idea, but also hear what he is saying about the issues with prototypes. 我非常喜欢@ luke-schafer的原型构想,但也听听他对原型问题的看法。 What about using a simple function? 使用一个简单的函数呢?

 function sortKeysAndDo( obj, worker ) { var keys = Object.keys(obj); keys.sort(); for (var i = 0; i < keys.length; i++) { worker(keys[i], obj[keys[i]]); } } function show( key, value ) { document.write( key + ' : ' + value +'<br>' ); } var a = new Array(); a['b'] = 1; a['z'] = 1; a['a'] = 1; sortKeysAndDo( a, show); var my_object = { 'c': 3, 'a': 1, 'b': 2 }; sortKeysAndDo( my_object, show); 

This seems to eliminate the issues with prototypes and still provide a sorted iterator for objects. 这似乎消除了原型的问题,并且仍然为对象提供了排序的迭代器。 I am not really a JavaScript guru, though, so I'd love to know if this solution has hidden flaws I missed. 我并不是真正的JavaScript专家,所以我很想知道这个解决方案是否存在我错过的隐藏缺陷。

<script type="text/javascript">
    var a = {
        b:1,
        z:1,
        a:1
    }; // your JS Object
    var keys = [];
    for (key in a) {
        keys.push(key);
    }
    keys.sort();
    var i = 0;
    var keyslen = keys.length;
    var str = '';
    //SORTED KEY ITERATION
    while (i < keyslen) {
        str += keys[i] + '=>' + a[keys[i]] + '\n';
        ++i;
    }
    alert(str);
    /*RESULT:
    a=>1
    b=>1
    z=>1
    */
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM