web-dev-qa-db-ja.com

配列は連想配列と索引付きの両方ですか?

JavaScriptの配列を連想およびインデックス化できますか?

位置またはキー値によって配列内のアイテムを検索できるようにしたいと思います。

37
puffpio

Javascriptには連想配列などはありません。 look連想配列のようなオブジェクトリテラルを使用できますが、それらには順序付けられていないプロパティがあります。通常のJavaScript配列は整数インデックスに基づいており、連想することはできません。

たとえば、次のオブジェクトの場合:

var params = {
    foo: 1,
    bar: 0,
    other: 2
};

たとえば、オブジェクトからプロパティにアクセスできます。

params["foo"];

また、for...inステートメントを使用してオブジェクトを反復処理することもできます。

for(var v in params) {
    //v is equal to the currently iterated property
}

ただし、プロパティの反復順序には厳密なルールはありません。オブジェクトリテラルを2回反復すると、異なる順序でプロパティが返される可能性があります。

28
Alex Rozanski

連想配列のウィキペディア定義 を読んだ後、私は伝統的なJavaScriptの伝承を破り、「はい、JavaScriptには連想配列があります」と言います。 JavaScript配列を使用すると、キーで値を追加、再割り当て、削除、および参照できます(キーは引用符で囲まれた文字列にすることができます)。

ただし、インデックスまたはキーのいずれかで同じ値を検索できるかどうか、何か違うことを求めているようです。これは連想配列の要件ではありません(Wikipediaの記事を参照してください。)連想配列は、インデックスによって値を取得する機能を提供する必要はありません。

JavaScript配列はJavaScriptオブジェクトに非常に似ています。

  arr=[];
  arr[0]="zero";
  arr[1]="one";
  arr[2]="two";
  arr["fancy"]="what?";

はい、それは配列です、そして、はい、非数値インデックスで済ますことができます。 (好奇心If盛なら、結局のところ、arr.lengthは3です。)

ほとんどの場合、配列を使用するときは数値インデックスに固執する必要があると思います。ほとんどのプログラマーが期待していることだと思います。

このリンクは、テーマに関する私のブログ投稿です。

22
Nosredna

ネイティブJSオブジェクトは、プロパティ名として文字列のみを受け入れます。これはtrue 数値配列インデックスの場合でも ;配列は、ほとんどのJS実装が数値インデックス付きプロパティを異なる方法で保存する限り(つまり、それらが密集している限り実際の配列に)、Vanillaオブジェクトとは異なり、それらを設定すると追加の操作(lengthプロパティの調整) 。

任意のキーを受け入れるマップを探している場合は、 非ネイティブ実装 を使用する必要があります。このスクリプトは、数値インデックスによるランダムアクセスではなく、高速反復を目的としているため、探しているものではないかもしれません。

あなたが求めていることをするマップのベアボーン実装は次のようになります:

_function Map() {
    this.length = 0;
    this.store = {};
}

Map.prototype.get = function(key) {
    return this.store.hasOwnProperty(key) ?
        this.store[key] : undefined;
};

Map.prototype.put = function(key, value, index) {
    if(arguments.length < 3) {
        if(this.store.hasOwnProperty(key)) {
            this.store[key].value = value;
            return this;
        }

        index = this.length;
    }
    else if(index >>> 0 !== index || index >= 0xffffffff)
        throw new Error('illegal index argument');

    if(index >= this.length)
        this.length = index + 1;

    this[index] = this.store[key] =
        { index : index, key : key, value : value };

    return this;
};
_

put()index引数はオプションです。

キーまたはインデックスを使用して、マップの値にアクセスできますmap

_map.get('key').value
map[2].value
_
9
Christoph

連想javascript配列に表示されるオブジェクトの順序は定義されておらず、実装ごとに異なります。そのため、特定の連想キーが常に同じインデックスにあると期待することはできません。

編集:

perspxが指摘しているように、javascriptには本当の連想配列はありません。ステートメントfoo["bar"]foo.bar

ブラウザがオブジェクト内の要素の順序を維持すると信頼している場合、関数を書くことができます

function valueForIndex(obj, index) {

    var i = 0;
    for (var key in obj) {

        if (i++ == index)
            return obj[key];
    }
}
6
Matt Bridges
var myArray = Array();
myArray["first"] = "Object1";
myArray["second"] = "Object2";
myArray["third"] = "Object3";

Object.keys(myArray);              // returns ["first", "second", "third"]
Object.keys(myArray).length;       // returns 3

最初の要素が必要な場合は、次のように使用できます。

myArray[Object.keys(myArray)[0]];  // returns "Object1"
6
Tom Prats

これが悪い習慣かどうかを知りたくてここに来て、その質問を理解していないように見える人がたくさんいるのを見つけました。

順序付けられているが、キーでインデックス付けできるデータ構造が必要だったので、ルックアップごとに繰り返しを必要としません。

実際には、これは非常に簡単ですが、それがひどい練習であるかどうかについてはまだ何も読んでいません。

var roygbiv = [];
var colour = { key : "red", hex : "#FF0000" };
roygbiv.Push(colour);
roygbiv[colour.key] = colour;
...
console.log("Hex colours of the Rainbow in order:");
for (var i = 0; i < roygbiv.length; i++) {
    console.log(roygbiv[i].key + " is " + roygbiv[i].hex);
}

// input = "red";
console.log("Hex code of input colour:");
console.log(roygbiv[input].hex);

重要なことは、オブジェクトが設定されるか、値が一致しなくなると、array [index]またはarray [key]の値を直接変更しないことです。配列にオブジェクトが含まれている場合、それらのオブジェクトのプロパティを変更でき、いずれかの方法で変更されたプロパティにアクセスできます。

1
Joel Roberts
var stuff = [];
stuff[0] = "foo";
stuff.bar = stuff[0]; // stuff.bar can be stuff["bar"] if you prefer
var key = "bar";
alert(stuff[0] + ", " + stuff[key]); // shows "foo, foo"
1
NickFitz

与えられた答えには同意しますが、ゲッターとセッターであなたが言っていることを実際に達成することができます。例えば:

var a = [1];
//This makes a["blah"] refer to a[0]
a.__defineGetter__("blah", function(){return this[0]});
//This makes a["blah"] = 5 actually store 5 into a[0]
a.__defineSetter__("blah", function(val){ this[0] = val});

alert(a["blah"]); // emits 1
a["blah"] = 5;
alert(a[0]); // emits 5

これはあなたが探しているものですか?ゲッターとセッターを行うための別のより現代的な方法があると思いますが、覚えていません。

0
Ryan

この潮流は変わりました。今、あなたはそれをすることができます...そしてもっと! Harmony Proxiesを使用すると、この問題をさまざまな方法で確実に解決できます。

harmony-reflect shimから少し助けを借りて、ターゲット環境がこれをサポートしていることを確認する必要があります。

Mozilla Developer Networkには、プロキシを使用して そのプロパティで配列項目オブジェクトを見つける の非常に良い例があります。

これが私のバージョンです。

  var players = new Proxy(
  [{
    name: 'monkey',
    score: 50
  }, {
    name: 'giraffe',
    score: 100
  }, {
    name: 'pelican',
    score: 150
  }], {
    get: function(obj, prop) {
      if (prop in obj) {
        // default behavior
        return obj[prop];
      }
      if (typeof prop == 'string') {

        if (prop == 'rank') {
          return obj.sort(function(a, b) {
            return a.score > b.score ? -1 : 1;
          });
        }

        if (prop == 'revrank') {
          return obj.sort(function(a, b) {
            return a.score < b.score ? -1 : 1;
          });
        }

        var winner;
        var score = 0;
        for (var i = 0; i < obj.length; i++) {
          var player = obj[i];
          if (player.name == prop) {
            return player;
          } else if (player.score > score) {
            score = player.score;
            winner = player;
          }
        }

        if (prop == 'winner') {
          return winner;
        }
        return;
      }

    }
  });

  console.log(players[0]); // { name: 'monkey', score: 50 }
  console.log(players['monkey']); // { name: 'monkey', score: 50 }
  console.log(players['zebra']); // undefined
  console.log(players.rank); // [ { name: 'pelican', score: 150 },{ name: 'giraffe', score: 100 }, { name: 'monkey', score: 50 } ]
  console.log(players.revrank); // [ { name: 'monkey', score: 50 },{ name: 'giraffe', score: 100 },{ name: 'pelican', score: 150 } ]
  console.log(players.winner); // { name: 'pelican', score: 150 }
0
Quickredfox