String Manipulation: convert flat string to a tree-like format

3220 views python
6

I have this tree:

Active Mode
   |___ Local (EU)
   |       |___ I don't want this line
   |___ International (WW)
   |       |___ I want this line <----
Passive Mode
   |___ Local (EU)
   |       |___ I also don't want this line
   |___ International (WW)
           |___ And neither this line

But due to circumstances, my python will see it as a flat string:

Active Mode
Local (EU)
I don't want this line
International (WW)
I want this line <----
Passive Mode
Local (EU)
I also don't want this line
International (WW)
And neither this line

Now it's pretty easy to get the line I want, I just do string.split(\n)[4]. The tricky part is:

  • the parents (Active Mode and Passive Mode) can be shuffled so the Active Mode would be after Passive Mode
  • the children (Local (EU) and International (WW)) can also be shuffled
  • A Parent might be missing or a child might be missing (so there is a chance that there is no Active Mode which means I should get something like None

One possible solution I thought of was to somehow convert the flat string into a multi-layer dictionary, list or json but I don't know how am I suppose to do it.

answered question

Can you have the line you want and not the line International (WW)?

I did not understand you. If you are asking whether the line "International (WW)" is a line that I can control or not then no. "Active Mode", "Passive Mode", "International (WW)" and "Local (EU)" are predefined variable that won't change. However their order or their presence can vary. Other lines are some variable that I don't know. (hope that I make sense)

I was asking something like this:Active Mode Local (EU) I don't want this line I want this line

1 Answer

3

I sketched some code, however it might be dangerous, since there is no guarantee in general, that the lines in modes don't collide with lines in mode names:

def parse(text):
    lines = text.split('\n')
    out = {}
    mode, options = None, None
    for l in filter(None, lines):
        if l.endswith(' Mode'):  # must be really careful here
            out[l] = out.get(l, {})
            mode = out[l]
            options = None
            continue

        # and here...
        if l.startswith('Local (') or l.startswith('International ('):
            mode[l] = mode.get(l, [])
            options = mode[l]
            continue

        options.append(l)

    return out

t = '''
Active Mode
Local (EU)
I don't want this line
International (WW)
I want this line <----
Passive Mode
Local (EU)
I also don't want this line
International (WW)
And neither this line
'''

print(parse(t))

posted this

Have an answer?

JD

Please login first before posting an answer.