1049

オブジェクトと配列を含むネストされたデータ構造があります。特定の値または複数の値 (またはキー) にアクセスするにはどうすれば情報を抽出できますか?

例えば:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

nameの 2 番目のアイテムのにアクセスするにはどうすればよいitemsですか?

4

31 に答える 31

1384

予選

JavaScript には、複数の値を含むことができるデータ型が 1 つだけあります: Object配列は特別な形式のオブジェクトです。

(プレーン) オブジェクトはフォームを持っています

{key: value, key: value, ...}

配列の形式は次のとおりです。

[value, value, ...]

配列とオブジェクトの両方が構造を公開しますkey -> value。配列のキーは数値でなければなりませんが、オブジェクトのキーとして任意の文字列を使用できます。キーと値のペアは「プロパティ」とも呼ばれます。

プロパティには、ドット表記を使用してアクセスできます

const value = obj.someProperty;

プロパティ名が有効な JavaScript識別子名[spec]ではない場合、または名前が変数の値である場合は、または角かっこ表記:

// the space is not a valid character in identifier names
const value = obj["some Property"];

// property name as variable
const name = "some Property";
const value = obj[name];

そのため、配列要素にはブラケット表記を使用してのみアクセスできます。

const value = arr[5]; // arr.5 would be a syntax error

// property name / index as variable
const x = 5;
const value = arr[x];

待って…JSONはどうですか?

JSON は、XML、YAML、CSV などと同様に、データのテキスト表現です。このようなデータを操作するには、まず JavaScript のデータ型、つまり配列やオブジェクトに変換する必要があります (これらのデータの操作方法については先ほど説明しました)。JSON を解析する方法は、質問「JavaScript で JSON を解析しますか?」で説明されています。.

参考資料

配列とオブジェクトにアクセスする方法は基本的な JavaScript の知識であるため、 MDN JavaScript ガイド、特にセクションを読むことをお勧めします



ネストされたデータ構造へのアクセス

ネストされたデータ構造は、他の配列またはオブジェクトを参照する配列またはオブジェクトです。つまり、その値は配列またはオブジェクトです。このような構造には、ドットまたはブラケット表記を連続して適用することでアクセスできます。

次に例を示します。

const data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

2 番目のアイテムのにアクセスするnameとします。

これを段階的に行う方法は次のとおりです。

ご覧のとおりdata、 はオブジェクトであるため、ドット表記を使用してそのプロパティにアクセスできます。プロパティには次のitemsようにアクセスします。

data.items

値は配列です。その 2 番目の要素にアクセスするには、ブラケット表記を使用する必要があります。

data.items[1]

この値はオブジェクトであり、再びドット表記を使用してnameプロパティにアクセスします。したがって、最終的には次のようになります。

const item_name = data.items[1].name;

または、特にドット表記の使用が無効になる文字が名前に含まれている場合は、いずれかのプロパティにブラケット表記を使用することもできます。

const item_name = data['items'][1]['name'];

プロパティにアクセスしようとしていますが、undefined戻ってきませんか?

を取得しているほとんどの場合undefined、オブジェクト/配列にはその名前のプロパティがありません。

const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined

console.logorを使用console.dirして、オブジェクト/配列の構造を調べます。アクセスしようとしているプロパティは、ネストされたオブジェクト/配列で実際に定義されている可能性があります。

console.log(foo.bar.baz); // 42

プロパティ名が動的で、事前にわからない場合はどうなりますか?

プロパティ名が不明な場合、またはオブジェクトのすべてのプロパティ/配列の要素にアクセスしたい場合は、オブジェクトの[MDN]ループと配列の [MDN for...in ]ループを使用して、すべてのプロパティ / 要素を反復処理できます。for

オブジェクト

のすべてのプロパティを反復するには、次のようにオブジェクトdataを反復できます。

for (const prop in data) {
    // `prop` contains the name of each property, i.e. `'code'` or `'items'`
    // consequently, `data[prop]` refers to the value of each property, i.e.
    // either `42` or the array
}

オブジェクトがどこから来ているか (そして何をしたいのか) に応じて、プロパティが実際にオブジェクトのプロパティであるか、継承されたプロパティであるかを反復ごとにテストする必要がある場合があります。Object#hasOwnProperty [MDN]でこれを行うことができます。

for...inwithの代わりに、 [MDN]hasOwnPropertyを使用してプロパティ名の配列を取得できます。Object.keys

Object.keys(data).forEach(function(prop) {
  // `prop` is the property name
  // `data[prop]` is the property value
});

配列

data.items arrayのすべての要素を反復するには、forループを使用します。

for(let i = 0, l = data.items.length; i < l; i++) {
    // `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
    // we can access the next element in the array with `data.items[i]`, example:
    // 
    // var obj = data.items[i];
    // 
    // Since each element is an object (in our example),
    // we can now access the objects properties with `obj.id` and `obj.name`. 
    // We could also use `data.items[i].id`.
}

配列を反復処理するために使用することもできfor...inますが、これを避けるべき理由があります: JavaScript で配列を使用する 'for(var item in list)' は悪い習慣と見なされるのはなぜですか? .

ECMAScript 5 のブラウザー サポートの増加に伴い、配列メソッドforEach [MDN]も興味深い代替手段になります。

data.items.forEach(function(value, index, array) {
    // The callback is executed for each element in the array.
    // `value` is the element itself (equivalent to `array[index]`)
    // `index` will be the index of the element in the array
    // `array` is a reference to the array itself (i.e. `data.items` in this case)
}); 

ES2015 (ES6) をサポートする環境では、[MDN]ループを使用することもできます。これは、配列に対してだけでなく、iterableに対しても機能します。for...of

for (const item of data.items) {
   // `item` is the array element, **not** the index
}

各反復でfor...ofは、反復可能な要素の次の要素を直接提供します。アクセスまたは使用する「インデックス」はありません。


データ構造の「深さ」がわからない場合はどうなりますか?

不明なキーに加えて、データ構造の「深さ」(つまり、ネストされたオブジェクトの数) も不明な場合があります。通常、深くネストされたプロパティにアクセスする方法は、正確なデータ構造によって異なります。

しかし、データ構造に繰り返しパターンが含まれている場合、たとえばバイナリ ツリーの表現の場合、ソリューションには通常、データ構造の各レベルに再帰的に [ウィキペディア]アクセスすることが含まれます。

以下は、バイナリ ツリーの最初のリーフ ノードを取得する例です。

function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild); // <- recursive call
    }
    else if (node.rightChild) {
        return getLeaf(node.rightChild); // <- recursive call
    }
    else { // node must be a leaf node
        return node;
    }
}

const first_leaf = getLeaf(root);

const root = {
    leftChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 42
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 5
        }
    },
    rightChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 6
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 7
        }
    }
};
function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild);
    } else if (node.rightChild) {
        return getLeaf(node.rightChild);
    } else { // node must be a leaf node
        return node;
    }
}

console.log(getLeaf(root).data);

未知のキーと深さを持つネストされたデータ構造にアクセスするより一般的な方法は、値の型をテストし、それに応じて行動することです。

ネストされたデータ構造内のすべてのプリミティブ値を配列に追加する例を次に示します (関数が含まれていないと仮定します)。オブジェクト (または配列) に遭遇した場合toArray、その値を再度呼び出すだけです (再帰呼び出し)。

function toArray(obj) {
    const result = [];
    for (const prop in obj) {
        const value = obj[prop];
        if (typeof value === 'object') {
            result.push(toArray(value)); // <- recursive call
        }
        else {
            result.push(value);
        }
    }
    return result;
}

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};


function toArray(obj) {
  const result = [];
  for (const prop in obj) {
    const value = obj[prop];
    if (typeof value === 'object') {
      result.push(toArray(value));
    } else {
      result.push(value);
    }
  }
  return result;
}

console.log(toArray(data));



ヘルパー

複雑なオブジェクトまたは配列の構造は必ずしも明白ではないため、各ステップで値を調べて、さらに先に進む方法を決定できます。console.log [MDN]console.dir [MDN]はこれを行うのに役立ちます。例 (Chrome コンソールの出力):

> console.log(data.items)
 [ Object, Object ]

data.itemsここでは、両方ともオブジェクトである 2 つの要素を持つ配列であることがわかります。Chrome コンソールでは、オブジェクトを展開してすぐに検査することもできます。

> console.log(data.items[1])
  Object
     id: 2
     name: "bar"
     __proto__: Object

これは、 がオブジェクトであることを示しています。展開すると、とdata.items[1]の 3 つのプロパティがあることがわかります。後者は、オブジェクトのプロトタイプ チェーンに使用される内部プロパティです。ただし、プロトタイプ チェーンと継承は、この回答の範囲外です。idname__proto__

于 2012-08-12T13:02:12.127 に答える
14
var ourStorage = {


"desk":    {
    "drawer": "stapler"
  },
"cabinet": {
    "top drawer": { 
      "folder1": "a file",
      "folder2": "secrets"
    },
    "bottom drawer": "soda"
  }
};
ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"

また

//parent.subParent.subsubParent["almost there"]["final property"]

基本的に、その下に展開する各子孫の間にドットを使用します。オブジェクト名が 2 つの文字列から作成されている場合は、["obj Name"] 表記を使用する必要があります。それ以外の場合は、ドットだけで十分です。

ソース: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects

これに追加すると、ネストされた配列へのアクセスは次のようになります。

var ourPets = [
  {
    animalType: "cat",
    names: [
      "Meowzer",
      "Fluffy",
      "Kit-Cat"
    ]
  },
  {
    animalType: "dog",
    names: [
      "Spot",
      "Bowser",
      "Frankie"
    ]
  }
];
ourPets[0].names[1]; // Outputs "Fluffy"
ourPets[1].names[0]; // Outputs "Spot"

ソース: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/

上記の状況を示す別のより有用なドキュメント: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

ドット ウォーキングによるプロパティ アクセス: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation

于 2018-08-19T23:01:34.340 に答える
9

ライブラリを含める場合は、 JSONPathを使用するのが最も柔軟なソリューションの 1 つです: https://github.com/s3u/JSONPath (ノードとブラウザー)

ユースケースの場合、json パスは次のようになります。

$..items[1].name

それで:

var secondName = jsonPath.eval(data, "$..items[1].name");
于 2014-06-26T12:43:46.673 に答える
8

私はJQueryを好みます。すっきりして読みやすいです。

$.each($.parseJSON(data), function (key, value) {
  alert(value.<propertyname>);
});
于 2016-02-24T15:55:02.000 に答える
6

アンダースコア js の方法

functional programmingこれは、組み込みオブジェクトを拡張せずに便利なヘルパーを提供する JavaScript ライブラリです。

解決:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

var item = _.findWhere(data.items, {
  id: 2
});
if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}

//using find - 

var item = _.find(data.items, function(item) {
  return item.id === 2;
});

if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}
于 2016-08-13T10:39:25.677 に答える
6

特定の基準を満たす 1 つ以上のオブジェクトを探している場合、query-jsを使用するいくつかのオプションがあります。

//will return all elements with an id larger than 1
data.items.where(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
data.items.first(function(e){return e.id > 1;});
//will return the first element with an id larger than 1 
//or the second argument if non are found
data.items.first(function(e){return e.id > 1;},{id:-1,name:""});

singleaと aもあり、それぞれ と とsingleOrDefaultよく似firstfirstOrDefaultいます。唯一の違いは、複数の一致が見つかった場合にスローされることです。

query-js の詳細については、この投稿から始めることができます

于 2015-06-17T12:16:08.833 に答える
5

質問者は 1 レベルのネストされたオブジェクトだけに関心があるとは思わないので、次のデモを提示して、深くネストされた json オブジェクトのノードにアクセスする方法を示します。よし、ID「5」のノードを見つけよう。

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'aaa',
    items: [{
        id: 3,
        name: 'ccc'
      }, {
        id: 4,
        name: 'ddd'
      }]
    }, {
    id: 2,
    name: 'bbb',
    items: [{
        id: 5,
        name: 'eee'
      }, {
        id: 6,
        name: 'fff'
      }]
    }]
};

var jsonloop = new JSONLoop(data, 'id', 'items');

jsonloop.findNodeById(data, 5, function(err, node) {
  if (err) {
    document.write(err);
  } else {
    document.write(JSON.stringify(node, null, 2));
  }
});
<script src="https://rawgit.com/dabeng/JSON-Loop/master/JSONLoop.js"></script>

于 2017-02-22T09:00:32.450 に答える
4

jQuery の grep関数を使用すると、配列をフィルター処理できます。

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

$.grep(data.items, function(item) {
    if (item.id === 2) {
        console.log(item.id); //console id of item
        console.log(item.name); //console name of item
        console.log(item); //console item object
        return item; //returns item object
    }

});
// Object {id: 2, name: "bar"}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

于 2017-08-28T11:25:30.973 に答える
4

構文jsonObject.keyを使用して値にアクセスできます。また、配列から値にアクセスする場合は、構文を使用できますjsonObjectArray[index].key

さまざまな値にアクセスしてアイデアを得るコード例を次に示します。

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

// if you want 'bar'
console.log(data.items[1].name);

// if you want array of item names
console.log(data.items.map(x => x.name));

// get the id of the item where name = 'bar'
console.log(data.items.filter(x => (x.name == "bar") ? x.id : null)[0].id);

于 2020-01-17T16:19:48.940 に答える