Перебирать ассоциативный массив Javascript в отсортированном порядке - PullRequest
107 голосов
/ 21 мая 2009

Допустим, у меня есть ассоциативный массив Javascript (a.k.a. hash, a.k.a dictionary):

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

Как перебрать ключи в отсортированном порядке? Если это помогает упростить вещи, мне даже не нужны значения (все они только номер 1).

Ответы [ 10 ]

130 голосов
/ 30 июня 2012

Вы можете использовать встроенный метод Object.keys :

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

(Примечание: это не работает в очень старых браузерах, не поддерживающих EcmaScript5, в частности IE6, 7 и 8. Для получения подробной обновленной статистики см. эту таблицу )

122 голосов
/ 21 мая 2009

Вы не можете перебирать их напрямую, но вы можете найти все ключи и затем просто отсортировать их.

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"]

Однако нет необходимости делать переменную 'a' массивом. Вы действительно просто используете его как объект и должны создать его так:

var a = {};
a["key"] = "value";
14 голосов
/ 21 мая 2009

Вы можете даже создать его на объекте:

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] ]);
    }
}

и использование:

var myObj = { a:1, b:2 };
myObj.iterateSorted(function(value)
{
    alert(value);
} 
6 голосов
/ 21 мая 2009

Я согласен с ответом Свингли , и я думаю, что это важный момент, которого многие из этих более сложных решений отсутствуют. Если вас интересуют только ключи в ассоциативном массиве и все значения равны «1», просто сохраните «ключи» как значения в массиве.

Вместо:

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

Использование:

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

Единственным недостатком этого является то, что вы не можете определить, установлен ли определенный ключ так же легко. См. этот ответ - функция javascript inArray для ответа на эту проблему. Одна проблема с представленным решением заключается в том, что a.hasValue('key') будет немного медленнее, чем a['key']. Это может иметь или не иметь значения в вашем коде.

3 голосов
/ 21 мая 2009

Нет краткого способа напрямую манипулировать «ключами» объекта Javascript. Это на самом деле не предназначено для этого. Есть ли у вас свобода помещать свои данные в нечто лучшее, чем обычный объект (или массив, как показывает пример кода)?

Если это так, и если ваш вопрос можно перефразировать как «Какой словарь-объект я должен использовать, если я хочу перебирать ключи в отсортированном порядке?» тогда вы можете разработать объект, подобный этому:

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]); }

Если вы не можете контролировать тот факт, что данные находятся в обычном объекте, эта утилита преобразует обычный объект в ваш полнофункциональный словарь:

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

Это было определение объекта (вместо многократно используемой функции конструктора) для простоты; редактировать по желанию.

2 голосов
/ 25 июля 2013

Вы можете использовать функцию keys из библиотеки underscore.js для получения ключей, затем метод массива sort() для их сортировки:

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

Функция 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);
};
2 голосов
/ 21 мая 2009

Получить ключи в первом цикле 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]);
0 голосов
/ 01 ноября 2015

Мне очень нравится идея прототипа @ luke-schafer, но я также слышу, что он говорит о проблемах с прототипами. Как насчет использования простой функции?

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);

Это, кажется, устраняет проблемы с прототипами и все еще предоставляет отсортированный итератор для объектов. Однако я не гуру JavaScript, поэтому я хотел бы знать, есть ли в этом решении скрытые недостатки, которые я пропустил.

0 голосов
/ 18 июня 2015

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>');
}
0 голосов
/ 21 мая 2009
<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...