Помогите с рекурсией JS

481
18 июля 2017, 21:31

Есть задача: написать в JS функцию которая генерирует из массива список. Функцию я написал но она работает только на первом уровне вложенности. Помогите сделать так чтобы работало не зависимо от количества уровней вложенности. Вот код:

var arr = [1,2,3,4,5,[4,6,7,9,0],6,7]
var generateList = function(a) {
    var ul = document.createElement('ul');
    a.forEach(function (item) {
    var li = document.createElement('li');
    if(!Array.isArray(item)) {
        li.innerText = item;
    } else {
        var new_ul = document.createElement('ul');
        item.forEach(function(item){
            var li = document.createElement('li');
            li.innerText = item;
            new_ul.appendChild(li);
        })
        li.appendChild(new_ul);
    }
    ul.appendChild(li);
})
    return ul;
}
document.body.appendChild(generateList(arr));
Answer 1

Задача рекурсивна сама по себе: если элемент - массив, то вызвать функцию generateList, передав ей этот элемент.

В коде для этого уже сделано половина дела. Нужно заменить цикл прохода по вложенному элементу

var new_ul = document.createElement('ul');
item.forEach(function(item){
    var li = document.createElement('li');
    li.innerText = item;
    new_ul.appendChild(li);
})

На вызов основной функции:

var new_ul = generateList(item);

Этого уже хватит для решения поставленной задачи.

В дополнение, можно заменить forEach на более подходящий reduce, так как в коде происходит ни что иное, как свертка массива в один элемент.

В итоге код может выглядеть так:

var arr = [1, [2, [3], 4], 5, [4, [6, 7], 9, 0], 6, 7] 
var generateList = function(items) { 
  return items.reduce((ul, item) => { 
    var li = document.createElement('li'); 
    if (!Array.isArray(item)) { 
      li.innerText = item; 
    } else { 
      var new_ul = generateList(item); 
      li.appendChild(new_ul); 
    } 
 
    ul.appendChild(li); 
    return ul; 
  }, document.createElement('ul')); 
} 
document.body.appendChild(generateList(arr));

Вариант без рекурсии: берем из списка элементы, пока не закончатся. Если элемент, число - добавляем li, если массив - добавляем каждый элемент массива в список, сохраняя с ним ul в который надо будет все добавлять.

var arr = [1, [2, [3], 4], 5, [4, [6, 7], 9, 0], 6, 7]; 
var generateList = function(items) { 
  var stack = items; 
  var root = document.createElement('ul'); 
 
  while (stack.length) { 
    var item = stack.shift(); 
    var ul = item.ul || root; 
    var value = item.value != null ? item.value : item; 
    var li = document.createElement('li'); 
 
    if (!Array.isArray(value)) { 
      li.innerText = value; 
    } else { 
      var nestedUl = document.createElement('ul'); 
      li.appendChild(nestedUl); 
      value.reduceRight((stack, el) => { 
        stack.unshift({ 
          value: el, 
          ul: nestedUl 
        }); 
        return stack; 
      }, stack); 
 
    } 
    ul.appendChild(li); 
  } 
  return root; 
} 
document.body.appendChild(generateList(arr));

Answer 2

var arr = [1,[[[[['Всё почти получилось']]]]],2,3,4,5,[4,6,7,[4,6,7,9,0,[4,6]],9,0],6,7] 
var generateList = function(a, parent) { 
    var ul = document.createElement('ul'); 
    a.forEach(item => { 
       var li = document.createElement('li'); 
       if(!Array.isArray(item)) { 
         li.innerText = item; 
       } else { 
         li.appendChild(generateList(item, ul)); 
       } 
       ul.appendChild(li); 
    }) 
    return ul; 
} 
document.body.appendChild(generateList(arr));

READ ALSO
Как правильно поймать Pinch event на body или HTML?

Как правильно поймать Pinch event на body или HTML?

Нужно поймать событие pinch на всю страницу целиком и заменить стандартный zoom на свойДолго мучался с hammerjs, все удобно и все работает, но напрочь...

309
Как включить ES6 синтаксис в webstorm?

Как включить ES6 синтаксис в webstorm?

Webstorm подсвечивает стрелочные функции красным и пишет Expression statement is not assignment or call, что делать?

335
Как выполнить скрипт с телефона? Гугл таблица

Как выполнить скрипт с телефона? Гугл таблица

Добрый день! Я чайник зеленый, прошу прощения, если такой вопрос задавалсяЕсть гугл таблица с почтовыми адресами

505
При очищении остается 0 в input value React.js

При очищении остается 0 в input value React.js

Разрабатывая компонент столкнулся с проблемой - input value при удаление значения из input до конца не удаляется - всегда остается 0Логика компонента...

315