как превратить строку во вложенный список с элементами, разделенными запятыми - PullRequest
2 голосов
/ 22 октября 2019

У меня есть строка, которая выглядит следующим образом:

'(a (b (c d e f)) g)'

Я хочу превратить ее в такой вложенный список:

['a', ['b', ['c', 'd', 'e', 'f']], 'g']

Я использовал эту функцию:

def tree_to_list(text, left=r'[(]', right=r'[)]', sep=r','):
    pat = r'({}|{}|{})'.format(left, right, sep)
    tokens = re.split(pat, text)    
    stack = [[]]
    for x in tokens:
        if not x or re.match(sep, x): continue
        if re.match(left, x):
            stack[-1].append([])
            stack.append(stack[-1][-1])
        elif re.match(right, x):
            stack.pop()
            if not stack:
                raise ValueError('error: opening bracket is missing')
        else:
            stack[-1].append(x)
    if len(stack) > 1:
        print(stack)
        raise ValueError('error: closing bracket is missing')
    return stack.pop()

Но результат не тот, который я ожидал. Между строками нет запятых:

['a', ['b', ['c' 'd' 'e' 'f']], 'g']

Не могли бы вы помочь мне с этим

Ответы [ 3 ]

5 голосов
/ 22 октября 2019

Вы можете использовать рекурсию с генератором:

import re
data = '(a (b (c d e f)) g)'
def group(d):
    a = next(d, ')')
    if a != ')':
        yield list(group(d)) if a == '(' else a
        yield from group(d)
print(next(group(iter(re.findall(r'\w+|[()]', data)))))

Выход:

['a', ['b', ['c', 'd', 'e', 'f']], 'g']
3 голосов
/ 22 октября 2019

Использование замены строк для преобразования ввода в строку с требуемым значением Python и literal_eval для преобразования его в само значение:

>>> import ast, re
>>> data = '(a (b (c d e f)) g)'
>>> s = re.sub(r'(\w+)', r'"\1"', data)         # quote words
>>> s = re.sub(r'\s+', ',', s)                  # whitespace to comma
>>> s = s.replace('(', '[').replace(')', ']')   # () -> []
>>> ast.literal_eval(s)
['a', ['b', ['c', 'd', 'e', 'f']], 'g']
1 голос
/ 22 октября 2019

Люди предложили свои собственные решения, но проблема с кодом, который вы используете, заключается в том, что для sep задано регулярное выражение r',', которое соответствует одной запятой. Как вы говорите, вы не используете запятые для разделения текста, вы используете пробелы. Если вы замените значение по умолчанию sep на r'\s' или вызовете функцию, подобную tree_to_list'(a (b (c d e f)) g)', sep=r'\s'), тогда она будет работать для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...