Рекурсивная функция до l oop на n-й глубине вложенности - PullRequest
2 голосов
/ 31 марта 2020

Данные, с которыми я работаю:

(у меня это в формате XML)

<root>

    <!-- level 1 nesting -->
    <main name="A" category="group">
        <sub name="A.1"></sub>
    </main>

    <!-- level 1 nesting -->
    <main name="B" category="group">
        <sub name="B.1"></sub>
    </main>

    <!-- level 1 nesting -->
    <main name="C" category="group">
        <sub name="C.1"></sub>
    </main>

    <!-- level 1 nesting -->
    <main name="D" category="group">
        <sub name="D.1"></sub>
    </main>

    <!-- level 2 nesting -->
    <main name="E" category="group">
        <sub name="E.1" category="group">
            <sub name="E.1.1"></sub>
        </sub>
    </main>

    <!-- level n nesting - this is what I need help with -->
    <main name="E" category="group">
        [...]
    </main>

</root>

Желаемый результат

  • Я хочу напечатать вышеизложенное в UL и LI в соответствии с их отношениями, показанными выше, чтобы получить древовидное представление.
  • Глубина вложения данных, с которыми я работаю, может быть разной (например, это может быть один элемент, или это может быть глубина вложения 100 - мы не знаем)
  • Мне нужно написать Решение, которое функционально обслуживает любой уровень глубины вложения
  • Любой тег (main или sub) со значением атрибута category "group" означает, что у него есть дочерние элементы
  • Первый тег уровня всегда равен main, остальное будет sub независимо от глубины вложения

Что я сейчас пытаюсь


def recursiveLoop(group)
    str = ""
    group.each { |g|

        str +=  "<ul>"
        str +=  "<li>#{g.attribute("name")}"

        if g.attribute("category").to_s == "group"
            recursiveLoop(g.css("sub"))
        else
            str += "</li></ul>"
        end
    }
    return str
end

Проблема с моим решением

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

Редактировать для CamiloVA Pic

Ответы [ 2 ]

2 голосов
/ 01 апреля 2020

Это работает

def recursiveLoop(group)
    str = ""
    group.each { |g|

        str +=  "<li>#{g.attribute("name")}"

        if g.attribute("category").to_s == "group"
            str += "<ul>"
            str += recursiveLoop(g.css("> sub"))
            str += "</ul>"
        end
        str += "</li>"
    }
    return str
end

Тем не менее, две вещи:

  1. Имейте основной <ul> и </ul> тег, обернутый вокруг результата recursiveLoop в разметке , Примерно так:
<%= sanitize "<ul>" + recursiveLoop(@groups) + "</ul>" %>

Это только для обеспечения узла root без запутывания в других зацикленных объектах.

Обязательно укажите > sub в селекторе css переменной XML g (забыл упомянуть, что я использую Nokogiri ), чтобы ограничить все подпункты их непосредственные родители.
1 голос
/ 01 апреля 2020

Как говорит @simplelime, вы можете поставить close tag после if block, и возвращаемое значение функции должно быть конкатенировано с одним и тем же начальным str, так что вы получите все рекурсивные дочерние элементы внутри каждого главного узла ; и в конце выполнения вернет большую результирующую строку.

def recursiveLoop(group)
    str = ""
    group.each { |g|

        str +=  "<ul>"
        str +=  "<li>#{g.attribute("name")}"

        if g.attribute("category").to_s == "group"
            str += recursiveLoop(g.css("sub"))
        end
        str += "</li></ul>"
    }
    return str
end
...