flat nested list -> nested list - mit fehlenden Einträgen..

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hab gerade einen knoten im Kopf und finde keine Lösung dazu:

Gegeben ist sowas:

Code: Alles auswählen

flat_list = [
    (1, u'headline 1 level 1'),
    (2, u'headline 2 level 2'),
    (2, u'headline 3 level 2'),
    (4, u'headline 4 level 4'),
    (1, u'headline 5 level 1'),
    (3, u'headline 6 level 3')
]
und das will ich in dieser Form bekommen:

Code: Alles auswählen

[ # Ebene 1
    (1, u'headline 1 level 1'),
    [ # Ebene 2
        (2, u'headline 2 level 2'),
        (2, u'headline 3 level 2'), 
        [ # Ebene 3, leer
            [ # Ebene 4
                (4, u'headline 4 level 4'),
            ],
        ],
    ],
    (1, u'headline 5 level 1'),
    [ # Ebene 2, leer
        [ # Ebene 3
            (3, u'headline 6 level 3'),
        ],
    ],
]
Muß was rekurives sein, aber ich weiß nicht wie ich die "leeren" Stellen handhaben soll.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: Dein Datendesign ist nicht optimal. Wie willst Du zwischen Headline-Einträgen und Ebenen-Listen unterscheiden? Listen sollten immer nur gleichartige Objekte enthalten. So wie ich das sehe hat ja eine Headline noch weitere Unterheadlines, leere Ebenen sind dann vielleicht Ebenen ohne Headline:

Code: Alles auswählen

[ # Ebene 1
    (1, u'headline 1 level 1', [
        # Ebene 2
        (2, u'headline 2 level 2', []),
        (2, u'headline 3 level 2', [
            # Ebene 3, leer
            (3, None, [
                # Ebene 4
                (4, u'headline 4 level 4', []),
            ]),
        ]),
    ]),
    (1, u'headline 5 level 1', [
        # Ebene 2, leer
        (2, None, [
            # Ebene 3
            (3, u'headline 6 level 3', []),
        ]),
    ]),
]
Lösen würde ich das mit einem Ebenen-Stack, der entsprechen gefüllt oder geleert wird.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Es geht um das neue <<toc>> macro in python-creole... Ich habe die flat_list von oben und brauche eigentlich eine verschachtelte <ul><li>... Das Datenformat ist nur ein "zwischenformat", bzw. ich brauche eigentlich mehr den Weg dahin.

Eine Tabel-Of-Contens soll halt auch funktionieren, wenn man Chaotische Überschriften macht, wie halt in dem Beispiel:

Code: Alles auswählen

= headline 1 level 1
== headline 2 level 2
== headline 3 level 2
==== headline 4 level 4
= headline 5 level 1
=== headline 6 level 3

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ungetestet:

Code: Alles auswählen

def nest(flat):
    tree = []
    stack = [tree]
    
    for element in flat_list:
        index, _ = element
        stack_length = len(stack)
        
        if index > stack_length:
            for _ in range(stack_length, index):
                l = []
                stack[-1].append(l)
                stack.append(l)
        elif index < stack_length:
            stack = stack[:index]
            
        stack[-1].append(element)
    
    return tree
Das sollte von der Komplexität optimal sein.
Das Leben ist wie ein Tennisball.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich glaube das ist das, was ich brauche! Danke.
Tippfehler hab ich auch gefunden :wink:

Ich versuche das mal zu nutzten.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Danke euch, ist nun drin und klappt: https://github.com/jedie/python-creole/ ... 520a4e95d8

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

jens hat geschrieben:Tippfehler hab ich auch gefunden :wink:
Das war natürlich ein Test von mir :wink:
Das Leben ist wie ein Tennisball.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Die beiden Methoden "flat_list2nest_list" und "nested_headlines2html" sind keine, weil sie "self" gar nicht brauchen. Die ganze Listenumformerei ist sowieso überflüssig, wenn es nur darum geht, HTML zu erzeugen.

Code: Alles auswählen

class TableOfContent(object):
    def __init__(self):
        self.max_depth = None
        self.headlines = []
        self._created = False
 
    def __call__(self, depth=None, **kwargs):
        """Called when if the macro <<toc>> is defined when it is emitted."""
        if self._created:
            return "<<toc>>"
    
        self._created = True
        if depth is not None:
            self.max_depth = depth
    
        return '<<toc>>'
 
    def add_headline(self, level, content):
        """Add the current header to the toc."""
        if self.max_depth is None or level <= self.max_depth:
            self.headlines.append(
                (level, content)
            )
 
    def emit(self, document):
        """Emit the toc where the <<toc>> macro was."""
        cur_level = 0
        result = []
        for level, content in self.headlines:
            while level>cur_level:
                result.append('\t'*cur_level+'<ul>')
                cur_level += 1
            while level<cur_level:
                cur_level -= 1
                result.append('\t'*cur_level+'</ul>')
            result.append('{0}<li><a href="#{1}">{1}</a></li>'.format('\t'*cur_level, content))
        while cur_level:
            cur_level -= 1
            result.append('\t'*cur_level+'</ul>')
        
        # FIXME: We should not use <p> here, because it doesn't match
        #        if no newline was made before <<toc>>
        substitution = "<p><<toc>></p>" if "<p><<toc>></p>" in document else "<<toc>>"
        return document.replace(substitution, '\n'.join(result), 1)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hm! Stimmt schon, das das umformen eigentlich nicht notwendig ist...

Das ist der Lösungsansatz den ich ursprünglich auch im Kopf hatte, aber richtig zusammen bekommen habe ich ihn nicht.

Nun habe ich das release aber schon fertig. Aber ich notiere mir das mal https://github.com/jedie/python-creole/issues/22 ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten