2016-07-19 23 views
5

muszę wyodrębnić ciągów z nawiasów zagnieżdżonych tak:Extract ciąg wewnątrz zagnieżdżonych nawiasów

[ this is [ hello [ who ] [what ] from the other side ] slim shady ] 

Wynik (kolejność nie ma znaczenia):

This is slim shady 
Hello from the other side 
Who 
What 

Uwaga, łańcuch może mieć N nawiasach i zawsze będą ważne, ale mogą, ale nie muszą być zagnieżdżone. Ponadto ciąg nie musi rozpoczynać się nawiasem.

Rozwiązania, które znalazłem w Internecie dla podobnego problemu, sugerują wyrażenie regularne, ale nie jestem pewien, czy zadziała w tym przypadku.

Myślałem o realizacji tego podobny do tego, jak możemy sprawdzić, czy ciąg ma wszystkie poprawne nawiasów:

przejść przez ciąg. Jeśli widzimy [przesuwamy jego indeks na stosie, jeśli widzimy], podciągamy stamtąd do bieżącego miejsca.

Musimy jednak usunąć ten podciąg z oryginalnego łańcucha, abyśmy nie dostali go jako części któregokolwiek z wyjść. Zamiast więc naciskać tylko przesuwając indeks do stosu, zastanawiałem się nad utworzeniem listy obiektów typu LinkedList, kiedy znajdziemy [wstawiamy ten węzeł na liście LinkedList. Umożliwi nam to łatwe usunięcie podciągu z listy LinkedList.

Czy to byłoby dobre podejście, czy też istnieje bardziej przejrzyste, znane rozwiązanie?

EDIT:

'[ this is [ hello [ who ] [what ] from the other [side] ] slim shady ][oh my [g[a[w[d]]]]]' 

powinien powrócić (kolejność nie ma znaczenia):

this is slim shady 
hello from the other 
who 
what 
side 
oh my 
g 
a 
w 
d 

Białe spacje nie ma znaczenia, to jest trywialne, aby usunąć później. Liczy się to, że można odróżnić różne treści w nawiasach. Albo oddzielając je w nowych liniach, albo mając listę łańcuchów.

+0

Jest to miły trudne pytanie, chcę rozwiązać go za pomocą rekurencji, ale to może być trochę trudne :) –

+0

iść dalej i spróbować them'all .. – Sundeep

+0

co to początkowy konstrukt z nawiasami? Tylko ciąg taki jak "astring =" [to [cześć [kim] [z drugiej strony] szczupły cień] "? Jeśli tak, dlaczego nie po prostu 'astring.replace (')', '')', 'astring.replace ('[', '')', a następnie 'astring.split()'? –

Odpowiedz

5

Kod ten skanuje tekst po znaku i popycha pusty list na stosie za każdym otwarciem [ i zdejmuje ostatnie pchnął list ze stosu dla każdego zamknięcia ].

text = '[ this is [ hello [ who ] [what ] from the other side ] slim shady ]' 

def parse(text): 
    stack = [] 
    for char in text: 
     if char == '[': 
      #stack push 
      stack.append([]) 
     elif char == ']': 
      yield ''.join(stack.pop()) 
     else: 
      #stack peek 
      stack[-1].append(char) 

print(tuple(parse(text))) 

Wyjście;

(' who ', 'what ', ' hello from the other side ', ' this is slim shady ') 
(' who ', 'what ', 'side', ' hello from the other ', ' this is slim shady ', 'd', 'w', 'a', 'g', 'oh my ') 
+0

Niesamowite, prawie dokładnie z tym, co miałem na myśli. Ponadto bardzo czysty i intuicyjny. – lorenzocastillo

5

To może być całkiem wygodnie rozwiązane za pomocą wyrażenia regularnego:

import re 

s= '[ this is [ hello [ who ] [what ] from the other [side] ] slim shady ][oh my [g[a[w[d]]]]]' 

result= [] 
pattern= r'\[([^[\]]*)\]' #regex pattern to find non-nested square brackets 
while '[' in s: #while brackets remain 
    result.extend(re.findall(pattern, s)) #find them all and add them to the list 
    s= re.sub(pattern, '', s) #then remove them 
result= filter(None, (t.strip() for t in result)) #strip whitespace and drop empty strings 

#result: ['who', 'what', 'side', 'd', 'hello from the other', 'w', 'this is slim shady', 'a', 'g', 'oh my'] 
+0

Proszę zobaczyć zaktualizowany post. Myślę, że twój kod się psuje. Nie masz komputera ze swoim ATM. Pójdę popatrzeć, kiedy mogę. – lorenzocastillo

+0

@orenzocastillo Zaktualizowano. –

1

Można reprezentować swoje mecze stosując strukturę drzewiastą.

class BracketMatch: 
    def __init__(self, refstr, parent=None, start=-1, end=-1): 
     self.parent = parent 
     self.start = start 
     self.end = end 
     self.refstr = refstr 
     self.nested_matches = [] 
    def __str__(self): 
     cur_index = self.start+1 
     result = "" 
     if self.start == -1 or self.end == -1: 
      return "" 
     for child_match in self.nested_matches: 
      if child_match.start != -1 and child_match.end != -1: 
       result += self.refstr[cur_index:child_match.start] 
       cur_index = child_match.end + 1 
      else: 
       continue 
     result += self.refstr[cur_index:self.end] 
     return result 

# Main script 
haystack = '''[ this is [ hello [ who ] [what ] from the other side ] slim shady ]''' 
root = BracketMatch(haystack) 
cur_match = root 
for i in range(len(haystack)): 
    if '[' == haystack[i]: 
     new_match = BracketMatch(haystack, cur_match, i) 
     cur_match.nested_matches.append(new_match) 
     cur_match = new_match 
    elif ']' == haystack[i]: 
     cur_match.end = i 
     cur_match = cur_match.parent 
    else: 
     continue 
# Here we built the set of matches, now we must print them 
nodes_list = root.nested_matches 
# So we conduct a BFS to visit and print each match... 
while nodes_list != []: 
    node = nodes_list.pop(0) 
    nodes_list.extend(node.nested_matches) 
    print("Match: " + str(node).strip()) 

Wyjście z tego programu będą:

Mecz: to jest Slim Shady
meczów: Witam z drugiej strony
Mecz: kto
meczów: co

+0

Zobacz zaktualizowany wpis. To nie daje prawidłowego wyniku – lorenzocastillo

+0

@lorenzocastillo złe granice podłańcuchów, poprawiłem to! – Rerito

1
a = '[ this is [ hello [ who ] [what ] from the other side ] slim shady ]' 
lvl = -1 
words = [] 
for i in a: 
    if i == '[' : 
     lvl += 1 
     words.append('') 
    elif i == ']' : 
     lvl -= 1 
    else: 
     words[lvl] += i 

for word in words: 
    print ' '.join(word.split()) 

To daje o/p -

jest Slim Shady

cześć z drugiej strony

kto co

+0

To nie jest poprawne wyjście: 'who' i' what' musi być różne dopasowania – Rerito

Powiązane problemy