2016-12-14 2 views
4

Пожалуйста, пройти через этот JavaScript Object:многомерный массив в объект

var obj = [{ 
    id: "A", 
    children: [{ 
    id: "B", 
    children: [{ 
     id: "C", 
     children: [{ 
     id: "D", 
     children: [{ 
      id: "E", 
      children: [{ 
      id: "F" 
      }] 
     }] 
     }, { 
     id: "G", 
     children: { 
      id: "H" 
     } 
     }] 
    }, { 
     id: "I" 
    }] 
    }, { 
    id: "J", 
    children: [{ 
     id: "K" 
    }] 
    }] 
}, { 
    id: "L" 
}, { 
    id: "M", 
    children: { 
    id: "N", 
    children: [{ 
     id: "O" 
    }] 
    } 
}, { 
    id: "P" 
}]; 

Как писать код JavaScript, чтобы рекурсивно разобрать его и напечатать все идентификаторы в консоли, так что выход выглядит следующим образом:

A 
B 
C 
D 
E 
F 
G 
H 
I 
J 
K 
L 
M 
N 
O 
P 

Вот как далеко я мог добраться. После этого я не мог думать о какой-либо логике.

for (i=0 ; i < obj.length ; i++){ 
     var objId = obj[i]; 
     for(j=i; j<1 ; j++){ 
      console.log(obj[j].id); 
      console.log(obj[j].children[j].id); 
     } 
    } 

Я не понимаю, какую логику следует применять здесь. Помогите.

+6

Вы пробовали что-нибудь себя еще? –

+0

Вам нужно пройти объект в определенном порядке, чтобы получить желаемый результат. Посмотрите на стратегии обхода и выберите подходящий. –

+1

вы должны использовать рекурсивную функцию. Принцип: проверка функции, если объект содержит детей, чтобы называть себя детьми;) –

ответ

5

Вы можете использовать итеративный и рекурсивный подход с помощью алгоритма depth-first search.

Редактировать: Extended для детей как объект.

var data = [{ id: "A", children: [{ id: "B", children: [{ id: "C", children: [{ id: "D", children: [{ id: "E", children: [{ id: "F" }] }] }, { id: "G", children: { id: "H" } }] }, { id: "I" }] }, { id: "J", children: [{ id: "K" }] }] }, { id: "L" }, { id: "M", children: { id: "N", children: [{ id: "O" }] } }, { id: "P" }]; 
 

 
data.forEach(function iter(a) { 
 
    console.log(a.id); 
 
    if (Array.isArray(a.children)) { 
 
     a.children.forEach(iter); 
 
     return; 
 
    } 
 
    if (a.children && typeof a.children === 'object') { // omit this part 
 
     iter(a.children);        // if children is 
 
    }             // always an array 
 
});

Эта версия собирает все необходимые данные и возвращает их в виде массива.

var data = [{ id: "A", children: [{ id: "B", children: [{ id: "C", children: [{ id: "D", children: [{ id: "E", children: [{ id: "F" }] }] }, { id: "G", children: { id: "H" } }] }, { id: "I" }] }, { id: "J", children: [{ id: "K" }] }] }, { id: "L" }, { id: "M", children: { id: "N", children: [{ id: "O" }] } }, { id: "P" }], 
 
    result = data.reduce(function iter(r, o) { 
 
     r.push(o.id); 
 
     if (Array.isArray(o.children)) { 
 
      return o.children.reduce(iter, r); 
 
     } 
 
     if (o.children && typeof o.children === 'object') { // omit this part 
 
      return iter(r, o.children);      // if children is 
 
     }             // always an array 
 
     return r; 
 
    }, []); 
 

 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

+1

Вы хорошо Нина? Это первый раз, когда вы используете forEach. Я старался, чтобы вы были принцессой карты уменьшить –

+0

Требования все о побочных эффектах. Трудно использовать «карту», ​​когда речь идет о побочных эффектах! –

+1

@NinaScholz как всегда хороший ответ Нина +1. Однако я пропускаю 'H' в консольном журнале. Что, если 'children' является' Object', а не 'Array', или я что-то здесь не вижу? Ох, и «Н». – DavidDomain

1

Вы можете использовать ниже функции ES6. Обратите внимание, что в двух местах вы не определили children как массив, который, как я предполагаю, является ошибкой. Если он отстутнут, я настоятельно рекомендую пересмотреть и сделать его единообразным.

function getIds(data) { 
 
    return data.reduce((acc, el) => acc.concat(el.id, getIds(el.children || [])), []) 
 
} 
 

 
var obj = [{ 
 
    id: "A", 
 
    children: [{ 
 
    id: "B", 
 
    children: [{ 
 
     id: "C", 
 
     children: [{ 
 
     id: "D", 
 
     children: [{ 
 
      id: "E", 
 
      children: [{ 
 
      id: "F" 
 
      }] 
 
     }] 
 
     }, { 
 
     id: "G", 
 
     children: [{ 
 
      id: "H" 
 
     }] 
 
     }] 
 
    }, { 
 
     id: "I" 
 
    }] 
 
    }, { 
 
    id: "J", 
 
    children: [{ 
 
     id: "K" 
 
    }] 
 
    }] 
 
}, { 
 
    id: "L" 
 
}, { 
 
    id: "M", 
 
    children: [{ 
 
    id: "N", 
 
    children: [{ 
 
     id: "O" 
 
    }] 
 
    }] 
 
}, { 
 
    id: "P" 
 
}]; 
 

 
console.log(getIds(obj).join('\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

+0

Да, как далеко я из ниндзя JS. Мастер благодарности –

+0

Вы изменили ввод так, чтобы 'children' всегда был массивом (что определенно является лучшим дизайном данных, но не тем, что указано OP). –

+0

Я хотел упомянуть об этом, поскольку я предполагал, что это была ошибка. Я добавлю этот комментарий к моему ответу. – trincot

0

Что вы показываете выглядит, как он просит глубину первого решения, так как порядок идентификаторов явно алфавитный и они упорядочены по первому встречаются затем по глубине.

В результате каждый обнаруженный идентификатор будет собран, а затем будут исследованы более глубокие идентификаторы. Это может и, вероятно, должно быть сделано с рекурсией.

Вот пример.


 
var obj=[{id:"A",children:[{id:"B",children:[{id:"C",children:[{id:"D",children:[{id:"E",children:[{id:"F"}]}]},{id:"G",children:{id:"H"}}]},{id:"I"}]},{id:"J",children:[{id:"K"}]}]},{id:"L"},{id:"M",children:{id:"N",children:[{id:"O"}]}},{id:"P"}]; 
 

 
var ids = [];//output holder 
 
(function tree(cur){ //recursive function 
 
for(var i = 0; i < cur.length; i++){ //iterate current set 
 
    ids.push(cur[i].id); //always store id 
 
    if(cur[i].children) tree(cur[i].children); //recurse if children exist 
 
} 
 
})(obj) //start from the top 
 
    
 
console.log(ids);

Смежные вопросы