JavaScriptの多次元連想配列


84

次のクエリ結果があります:(key1とkey2は任意のテキストである可能性があります)

id   key1     key2     value

1    fred     apple    2
2    mary     orange   10
3    fred     banana   7
4    fred     orange   4
5    sarah    melon    5
...

そして、次のようにすべてのレコードをループするグリッド(おそらく配列として)にデータを保存したいと思います。

         apple    orange   banana  melon
fred        2        4         7     -
mary        -        10        -     -
sarah       -        -         -     5

PHPでは、連想配列を使用すると、これは非常に簡単です。

$result['fred']['apple'] = 2;

しかし、JavaScriptでは、このような連想配列は機能しません。たくさんのチュートリアルを読んだ後、私が得ることができたのはこれだけでした:

arr=[];
arr[1]['apple'] = 2;

しかし、arr['fred']['apple'] = 2;動作しません。オブジェクトの配列を試しましたが、オブジェクトのプロパティをフリーテキストにすることはできません。チュートリアルを読めば読むほど、混乱してしまいます...

どんなアイデアでも大歓迎です:)


返信ありがとうございますが、クエリ結果をループしているので、一度に1つずつ値を設定したいと思います。例の行(Mattの例から取得)var grid = {};grid['aa']['bb'] = 1;は、「Uncaught TypeError:Undefinedのプロパティ 'bb'を設定できません」を返します。私は間違っている可能性がありますが、ほとんどの例では、初期化時にデータを知る必要があります。
Omiod 2010

var grid = {}; grid['aa'] = {}; grid['aa']['bb'] = 1;うまくいくことがわかりました。より複雑なテストは失敗しますが、私は正しい道を
進ん

2
私の答えで述べたように、最初にサブオブジェクトを初期化する必要があります。var grid = {}; grd ['aa'] = {}; 次に、 grid ['aa'] ['bb'] = 1を実行できます。サブオブジェクトがすでに初期化されているかどうかを確認する方法はたくさんあります(私の回答で述べたように)。したがって、既存のオブジェクトを上書きしません。オブジェクト。
マット

いくつかの追加コードで私の答えを更新しました。オブジェクトの深さやデータの取得方法はわかりませんが、正しい方向を示すことができれば幸いです
Matt

回答:


152

連想配列と同じように「読み取る」通常のJavaScriptオブジェクトを使用するだけです。最初にそれらも初期化することを忘れないでください。

var obj = {};

obj['fred'] = {};
if('fred' in obj ){ } // can check for the presence of 'fred'
if(obj.fred) { } // also checks for presence of 'fred'
if(obj['fred']) { } // also checks for presence of 'fred'

// The following statements would all work
obj['fred']['apples'] = 1;
obj.fred.apples = 1;
obj['fred'].apples = 1;

// or build or initialize the structure outright
var obj = { fred: { apples: 1, oranges: 2 }, alice: { lemons: 1 } };

値を調べている場合は、次のようなものがある可能性があります。

var people = ['fred', 'alice'];
var fruit = ['apples', 'lemons'];

var grid = {};
for(var i = 0; i < people.length; i++){
    var name = people[i];
    if(name in grid == false){
        grid[name] = {}; // must initialize the sub-object, otherwise will get 'undefined' errors
    }

    for(var j = 0; j < fruit.length; j++){
        var fruitName = fruit[j];
        grid[name][fruitName] = 0;
    }
}

本番コード(Chrome拡張機能)でこの例を使用することができ、正常に動作します。ありがとう。最後に、JSでオブジェクトを処理する方法を取得しました!
Omiod 2010

3
この答えを十分に賛成することはできません!オブジェクトが未定義を継続的に返す原因となったのは、サブオブジェクトを初期化していないことでした。 だから、これを必ず行ってください! 例: grid[name] = {};
Jason Pudzianowski 2012年

1
@Matt []のセットを1つだけ使用してobj.fred.applesを取得する方法はありますか?私はそうではないと思います。obj["fred.apples"]
theB3RV 2017年

配列の数がわからない場合はどうなりますか。たとえば、コード[javasript] var people = ['fred'、 'alice']; var Fruit = ['apples'、 'lemons']; var color = ['red'、 'blue'] var
.....-

数値インデックスでobj(fred)の最初のアイテムにアクセスできますか?obj [0]のように、apples:1、oranges:2になります。最後のアイテム(アリスでレモンになります:1)にアクセスできますか? `
Timo

26

それがいない場合は持っている配列であることを、あなたは「多次元」JSオブジェクトを作成することができます...

<script type="text/javascript">
var myObj = { 
    fred: { apples: 2, oranges: 4, bananas: 7, melons: 0 }, 
    mary: { apples: 0, oranges: 10, bananas: 0, melons: 0 }, 
    sarah: { apples: 0, oranges: 0, bananas: 0, melons: 5 } 
}

document.write( myObject[ 'fred' ][ 'apples' ] );
</script>

JSONは、実際にはJavaScriptオブジェクトの「文字列化された」形式です。あなたが持っているのはJSONではなく、JavaScriptオブジェクトだけです。
マット

ありがとう、マット。投稿を更新しました。
charliegriefer 2010

1
@ charliegriefer、document.write行を次のようにすべきではありません: "document.write(myObj ......"
john

13

Javascriptは柔軟です:

var arr = {
  "fred": {"apple": 2, "orange": 4},
  "mary": {}
  //etc, etc
};

alert(arr.fred.orange);
alert(arr["fred"]["orange"]);
for (key in arr.fred)
    alert(key + ": " + arr.fred[key]);

8
変数名「arr」は、実際には配列ではなくオブジェクトであるため、ここでは誤った名前であると言えます。
マット

私は怠惰な犬なので、あなたの解決策を使うことはできません。もし私が熱心だったら、あなたのサブアレイの例で私の道を見つけるでしょう;)とにかく、あなたの努力に感謝します。
ティモ

9

すべての要素を適切な方法で取得する必要があったので、このSOサブジェクト「2次元連想配列/オブジェクトのトラバーシング」に遭遇しました。名前に関係なく、機能が重要であるためです。

var imgs_pl = { 
    'offer':        { 'img': 'wer-handwritter_03.png', 'left': 1, 'top': 2 },
    'portfolio':    { 'img': 'wer-handwritter_10.png', 'left': 1, 'top': 2 },
    'special':      { 'img': 'wer-handwritter_15.png', 'left': 1, 'top': 2 }
};
for (key in imgs_pl) { 
    console.log(key);
    for (subkey in imgs_pl[key]) { 
        console.log(imgs_pl[key][subkey]);
    }
}

ループが通常行く方法であるため、答えを受け入れる必要があります。
ティモ

5

一部のアプリケーションでは、JavaScriptの多次元連想配列に対してはるかに簡単なアプローチがあるようです。

  1. すべての配列の内部表現が実際にはオブジェクトのオブジェクトであるとすると、数値でインデックス付けされた要素のアクセス時間は、実際には結合(テキスト)インデックス付き要素のアクセス時間と同じであることが示されています。

  2. 第1レベルの連想インデックス付き要素のアクセス時間は、実際の要素の数が増えても増加しません。

これを考えると、多次元要素の同等性を作成するために連結文字列アプローチを使用する方が実際に優れている場合が多くあります。例えば:

store['fruit']['apples']['granny']['price] = 10
store['cereal']['natural']['oats']['quack'] = 20

に行く:

store['fruit.apples.granny.price'] = 10
store['cereal.natural.oats.quack'] = 20

利点は次のとおりです。

  • サブオブジェクトを初期化したり、オブジェクトを最適に組み合わせる方法を理解したりする必要はありません
  • シングルレベルのアクセス時間。オブジェクト内のオブジェクトには、アクセス時間のN倍が必要です
  • Object.keys()を使用して、すべてのディメンション情報を抽出できます。
  • キーで関数regex.test(string)とarray.map関数を使用して、必要なものを正確に引き出すことができます。
  • ディメンションに階層はありません。
  • 「ドット」は任意です-アンダースコアを使用すると、実際には正規表現が簡単になります
  • JSONをこの形式に「フラット化」するためのスクリプトもたくさんあります
  • キーリストにある他のすべての優れた配列処理関数を使用できます

3

プロパティ名が整数の場合、連想配列のプロパティの配列の値を取得します。

プロパティ名が整数である連想配列から始めます。

var categories = [
    {"1":"Category 1"},
    {"2":"Category 2"},
    {"3":"Category 3"},
    {"4":"Category 4"}
];

アイテムを配列にプッシュします。

categories.push({"2300": "Category 2300"});
categories.push({"2301": "Category 2301"});

配列をループして、プロパティ値を使用して何かを実行します。

for (var i = 0; i < categories.length; i++) {
    for (var categoryid in categories[i]) {
        var category = categories[i][categoryid];
        // log progress to the console
        console.log(categoryid + " : " + category);
        //  ... do something
    }
}

コンソール出力は次のようになります。

1 : Category 1
2 : Category 2
3 : Category 3
4 : Category 4
2300 : Category 2300
2301 : Category 2301

ご覧のとおり、連想配列の制限を回避し、プロパティ名を整数にすることができます。

注:私の例の連想配列は、Dictionary []オブジェクトをシリアル化した場合に使用するjsonです。


3

配列を使用せず、オブジェクトを使用してください。

var foo = new Object();

2
new Object()Object.prototypeに奇妙なものが付加されている可能性があるため、を使用しないでください。:オブジェクトリテラルの使用var foo = {};
マイケルPaulukonis

1
@Michael {}は新しいObject()の単なる構文糖衣だと思いました。[]はnewArray()の略です
Matt

1
私のChromeJSコンソールからは、これらの構造は両方とも、プロトタイプを含めて同じように見えます。Object.prototype.foo = function(){}を追加しても、両方に表示されます。
マット

1
@マット私は間違っていると思います私はnew Array()それを避けるべきであると混同していました。うーん。
Michael Paulukonis 2010

1
@Michaelなぜ新しいArray()を避ける必要があるのですか?
マット

2

必ずしもオブジェクトを使用する必要はありません。通常の多次元配列で使用できます。

これはオブジェクトなしの私の解決策です:

// Javascript
const matrix = [];

matrix.key1 = [
  'value1',
  'value2',
];

matrix.key2 = [
  'value3',
];

PHPではこれは次と同等です。

// PHP
$matrix = [
    "key1" => [
        'value1',
        'value2',
    ],
    "key2" => [
        'value3',
    ]
];

1
後でこれをどのようにループ(それぞれ使用)しますか?
Sagive SEO 2018

0

<script language="javascript">

// Set values to variable
var sectionName = "TestSection";
var fileMap = "fileMapData";
var fileId = "foobar";
var fileValue= "foobar.png";
var fileId2 = "barfoo";
var fileValue2= "barfoo.jpg";

// Create top-level image object
var images = {};

// Create second-level object in images object with
// the name of sectionName value
images[sectionName] = {};

// Create a third level object
var fileMapObj = {};

// Add the third level object to the second level object
images[sectionName][fileMap] = fileMapObj;

// Add forth level associate array key and value data
images[sectionName][fileMap][fileId] = fileValue;
images[sectionName][fileMap][fileId2] = fileValue2;


// All variables
alert ("Example 1 Value: " + images[sectionName][fileMap][fileId]);

// All keys with dots
alert ("Example 2 Value: " + images.TestSection.fileMapData.foobar);

// Mixed with a different final key
alert ("Example 3 Value: " + images[sectionName]['fileMapData'][fileId2]);

// Mixed brackets and dots...
alert ("Example 4 Value: " + images[sectionName]['fileMapData'].barfoo);

// This will FAIL! variable names must be in brackets!
alert ("Example 5 Value: " + images[sectionName]['fileMapData'].fileId2);
// Produces: "Example 5 Value: undefined".

// This will NOT work either. Values must be quoted in brackets.
alert ("Example 6 Value: " + images[sectionName][fileMapData].barfoo);
// Throws and exception and stops execution with error: fileMapData is not defined

// We never get here because of the uncaught exception above...
alert ("The End!");
</script>


0
    var myObj = [];
    myObj['Base'] = [];
    myObj['Base']['Base.panel.panel_base'] = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',  AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };
    myObj['Base']['Base.panel.panel_top']  = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };

    myObj['SC1'] = [];
    myObj['SC1']['Base.panel.panel_base'] = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',  AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };
    myObj['SC1']['Base.panel.panel_top']  = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };


    console.log(myObj);

    if ('Base' in myObj) {
      console.log('Base found');

      if ('Base.panel.panel_base' in myObj['Base'])  {
        console.log('Base.panel.panel_base found'); 


      console.log('old value: ' + myObj['Base']['Base.panel.panel_base'].Context);  
      myObj['Base']['Base.panel.panel_base'] = 'new Value';
      console.log('new value: ' + myObj['Base']['Base.panel.panel_base']);
      }
    }

出力:

  • ベースが見つかりました
  • Base.panel.panel_baseが見つかりました
  • 古い値:ベース
  • 新しい値:新しい値

配列操作は機能します。問題はない。

反復:

     Object.keys(myObj['Base']).forEach(function(key, index) {            
        var value = objcons['Base'][key];                   
      }, myObj);

2
stackoverflowへようこそ。回答を編集して、コードスニペットが問題を解決する理由を説明してください。詳細:回答する方法
Djensen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.