Можно ли получить доступ к дочерним элементам объекта без знания родительского элемента?

#javascript #arrays #json

#javascript #массивы #json

Вопрос:

У меня есть объект:

 [
    {"ML":[
        {"TeamName":"Team 1","League":"League 1"},
        {"TeamName":"Team 2","League":"League 2"},
        {"TeamName":"Team 3","League":"League 3"}
    ]},
    {"3A":[
        {"TeamName":"Team 4","League":"League 1"},
        {"TeamName":"Team 5","League":"League 2"},
        {"TeamName":"Team 6","League":"League 3"}
    ]},
    {"2A":[
        {"TeamName":"Team 7","League":"League 1"},
        {"TeamName":"Team 8","League":"League 2"},
        {"TeamName":"Team 9","League":"League 3"}
    ]}
]
 

Как я могу получить доступ "TeamName" к каждой группе без указания родительского элемента (например "ML" )?

Обычно, это ML.TeamName , возможно, сделать что-то вроде x.TeamnName ?

Причина этого заключается в том, что названия групп являются динамичными и непредсказуемыми.

В основном я хочу перебирать группы (родительские группы с дочерними элементами, установленными внутри них). Думайте об этом как о создании <ul> для каждой группы (с именем группы в качестве заголовка) и списка дочерних элементов, в <li> котором есть значение «Имя_команды».

Я использую jQuery и хочу получить такие результаты:

 <h4>ML</h4>
<ul>
  <li>Team 1</li>
  <li>Team 2</li>
  <li>Team 3</li>
</ul>

<h4>3A</h4>
<ul>
  <li>Team 4</li>
  <li>Team 5</li>
  <li>Team 6</li>
</ul>

<h4>2A</h4>
<ul>
  <li>Team 7</li>
  <li>Team 8</li>
  <li>Team 9</li>
</ul>
 

Комментарии:

1. Какой результат вы ищете? Набор имен команд или одно имя?

2. Конечно, но какой из них вы хотите, если скажете x.TeamName ? ML, 3A или 2A? Есть причина, по которой у них есть ключевые значения… таким образом, вы знаете, о каком из них идет речь. Конечно, вы всегда можете перебрать их, а затем что-то сделать с каждым из них.

3. Вы могли бы получить все родительские элементы и перебирать их…

4. В основном я хочу перебирать группы (родительские группы с дочерними элементами, установленными внутри них). Подумайте об этом как о создании <ul> для каждой группы (с именем группы в качестве заголовка) и списка дочерних элементов, в <li> которых имеет значение "TeamName" .

5. @DrCord не могли бы вы подсказать мне, как это сделать?

Ответ №1:

Если ваш объект хранится в data , вы можете использовать ES5 map :

 data.Result.map(function(obj){
    for(var i in obj) if(obj.hasOwnProperty(i))
        return obj[i].map(function(obj){
            return obj.TeamName
        });
});
 

Или упрощение с помощью функций стрелки ES6:

 data.Result.map(obj => {
    for(var i in obj) if(obj.hasOwnProperty(i))
        return obj[i].map(obj => obj.TeamName);
});
 

С небольшими изменениями вы можете получить этот HTML-код (обратите внимание, что он уязвим для внедрения html).

 wrapper.innerHTML  = data.Result.map(obj => {
    for(var i in obj) if(obj.hasOwnProperty(i))
        return '<h4>' i '</h4>n'
              obj[i].map(obj => 't<li>' obj.TeamName '</li>n').join('');
}).join('');
 

Этот путь не уязвим:

 data.Result.forEach(obj => {
    for(var i in obj) if(obj.hasOwnProperty(i)) {
        var h4 = document.createElement('h4'),
            ul=document.createElement('ul');
        h4.appendChild(document.createTextNode(i));
        wrapper.appendChild(h4);
        obj[i].forEach(obj => {
            var li = document.createElement('li');
            li.appendChild(document.createTextNode(obj.TeamName));
            ul.appendChild(li);
        });
        wrapper.appendChild(ul);
        return;
    }
})
 

Комментарии:

1. Потрясающе, большое вам спасибо! Я должен заглянуть в ES5 / ES6, выглядит интересно. result на самом деле это массив объектов, как мне его сохранить data ? Есть ли способ решить, куда будет введен html (например, добавление jQuery)? Допустим, я хочу добавить его <div class="content"></div> .

2. @Steve Если вы хотите заменить data , вы можете просто использовать data = data.Result.map(/* ... */) . HTML будет введен в wrapper .

3. моя проблема заключалась в том, что у меня были данные в массиве объектов, таких как: console.log(results) shows [obj1, obj2, obj3] , и при использовании вашего кода я получаю Uncaught SyntaxError: Unexpected token > при использовании results.forEach(... я обновил свой вопрос выше.

4. @Steve Это может быть связано с тем, что ваш браузер не поддерживает функции ES6 arrow (к сожалению, в настоящее время его поддерживает только Firefox). Попробуйте заменить obj => { на function(obj){ .

5. пошел с другим решением, но ваш код выглядит так, как будто это правильный ответ для браузера, поддерживающего ES6. Спасибо! 🙂

Ответ №2:

Используйте обозначение в скобках:

 Result["ML"].TeamName
 

Если вы хотите знать все, что есть в списке

 var result = JSON.parse(...);

for (var i = 0; i < result.Result.length; i  ) {
  console.log(result.Result[i])
}
 

Ответ №3:

Предполагая, что цель состоит в том, чтобы устранить дополнительный уровень и выровнять команды, рассмотрите следующее (скрипка). Он использует базовое зацикливание, но, надеюсь, показывает процесс деконструкции.

 var results = json.Result;
var teams = [];
for (var i = 0; i < results.length; i  ) {
   var conf = results[i];
   // conf will be like {ML: ..}
   for (var p in conf) {
       // Enumerate properties, p is "ML", etc. In the given JSON there
       // will only be one property to enumerate.
       if (conf.hasOwnProperty(p)) {               
           var confTeams = conf[p];
           // confTeams is like [{TeamName:..},..]
           teams = teams.concat(confTeams)
       }
   }
};
 

Теперь teams содержит преобразованные данные, такие как:

 [ {"TeamName":"Team 1","League":"League 1"},
  {"TeamName":"Team 2","League":"League 2"},
  .. ]
 

Комментарии:

1. спасибо за ваш ответ, но на самом деле они все еще нужны мне в группе. Я добавил дополнительные детали к своему вопросу для уточнения.

2. @Steve, если они все еще нужны в группе, см. Ответ Ориоля и / или просто выполните обработку как есть (например, измените циклы выше, чтобы немедленно обработать значение, не возвращая сплющенную форму).

3. будет сделано. Еще раз спасибо за вашу помощь. 🙂

Ответ №4:

Если вы используете библиотеку, такую как Lodash или подчеркивание

если вам не нужно знать оригинальный ключ…

 var list = _.reduce(j.Result,function(c,v,i,l){
  return c.concat(_.values(v)[0]);
},[])
 

если вы хотите проиндексировать исходный ключ внутри объектов…

 var list = _.reduce(j.Result,function(c,v,i,l){
  return c.concat(_.map(_.values(v)[0],function(vv,ii){
    vv.key = _.keys(v)[0]
    return vv; // change each object here
  }));
},[]);

console.log(list)
 

JSBIN