ソートされた順序でJavascript連想配列を反復する


109

私がJavascript連想配列(別名ハッシュ、別名辞書)を持っているとしましょう:

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

ソートされた順序でキーを反復するにはどうすればよいですか?それが物事を単純化するのに役立つなら、私は値さえも必要としません(それらはすべてただの数1です)。


11
なぜnew Array()構文を使用し、それをオブジェクトのように使用するのですか?
ルークシェーファー、

@Luke ..私も最初はPHPのバックグラウンドからやってきた。私は今でも学びました:)
アレックス

20
@ルーク:私は経験が浅いので、そうです。正しい方法で回答を投稿できますか?
マイク

4
任意のオブジェクトを作成できます。JavaScriptでは、dictionary /「名前付き配列」と通常のオブジェクトの間に違いはありません。したがって、abでa ['b']にアクセスでき、その逆も可能です。オブジェクトを作成する最短の方法はa = {};です。
Lodewijk

回答:


124

それらを直接反復することはできませんが、すべてのキーを見つけて並べ替えることができます。

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

28
次の場合は、常にforループをチェックインする必要がありますobj.hasOwnProperty(key)
viam0Zah 2009年

3
@Lalit-Torokのコメントを参照している場合、これは、信頼できないオブジェクトのプロトタイプを妨害するものがないためです。
Luke Schafer、2010年

1
+1 to Torok。回答にhasOwnProperty()が含まれていると便利です。
Jon Onstott、2011

136

Object.keys組み込みメソッドを使用できます。

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

(注:これは、ECmaScript5をサポートしていない非常に古いブラウザー、特にIE6、7、8では機能しません。最新の統計の詳細については、この表を参照してください


@ michael667おそらくIE 7と8がまだ広く使用されているため(残念ながらMSに感謝)
Alexander Reifinger

1
幸いなことに、現時点でIE7は0.5%、IE8は8%です。
molnarg 2013

3
if (!Object.keys) { Object.keys = function (obj) { var op, result = []; for (op in obj) { if (obj.hasOwnProperty(op) { result.push(op) } } return result }
ジョーダンライター2013年

私はこれが大好きです、ありがとう。これを利用した私のコードは、$(Object.keys(list))。map(function(i、e){return n + '=' + list [n];})。get()。join( '&');です。// URLクエリ文字列の連結
Elaine

1
2016年の更新:これはおそらく受け入れられる答えになるはずです
rinogo

14

オブジェクトにプロトタイプを作成することもできます。

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

3
私はこの回答に賛成しましたが、それはかなり良さそうに見えましたが、jquery :( stackoverflow.com/questions/1827458/…を壊すことが判明し 、一般的には非常に悪い考えと見なされています。「Object.prototypeを拡張するべきではありません。 jQueryを中断します。これは、JavaScriptの「object-as-hashtables」機能を完全に壊します。そうしないでください
。JohnResigに質問

あのね?私もプロトタイプが嫌いです:)私はそれらを使用することはなく、積極的に使用を控えています。3.5年前にこの答えを書いたとき、私はこのように感じていましたが、とにかくそれを提案しました...情報を提供してくれてありがとう。余談ですが、オブジェクトの反復時に常にhasOwnPropertyを使用する必要があるため、フレームワークを壊すべきではありません
Luke Schafer

キーの代わりに値を使用して、key -> value関係を維持しながらソートする例を次に示します
Xeoncross、2015

6

スウィングリーの答えに同意するます。これらのより複雑なソリューションの多くが欠けていることが重要なポイントだと思います。連想配列のキーのみに関心があり、すべての値が「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());

これの1つの欠点は、特定のキーが簡単に設定されているかどうかを判断できないことです。この問題の回答については、javascript関数inArrayに対するこの回答を参照してください。提示されたソリューションの1つの問題は、a.hasValue('key')それよりも少し遅くなることa['key']です。それはあなたのコードで重要かもしれないし、重要ではないかもしれません。


3

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

最初のforループでキーを取得し、ソートして、2番目の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]);

2

underscore.jsライブラリのkeys関数を使用してキーを取得し、次に配列メソッドを使用してキーをソートできます。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);
};

0
<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>

0

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

私は@ 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の第一人者ではないので、このソリューションに見逃した欠陥が隠されているかどうか知りたいです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.