Как я разделяю строку на список?

Если у меня есть эта строка:

2+24*48/32

что является самым эффективным подходом для создания этого списка:

['2', '+', '24', '*', '48', '/', '32']

36
задан Honest Abe 13 August 2012 в 06:11
поделиться

9 ответов

Это именно так происходит, что маркеры, Вы хотите разделение, уже являются маркерами Python, таким образом, можно использовать встроенное tokenize модуль. Это - почти острота:

from cStringIO import StringIO
from tokenize import generate_tokens
STRING = 1
list(token[STRING] for token 
     in generate_tokens(StringIO('2+24*48/32').readline)
     if token[STRING])
['2', '+', '24', '*', '48', '/', '32']
50
ответ дан Glyph 27 November 2019 в 05:10
поделиться

Можно использовать split от re модуль.

re.split (шаблон, строка, maxsplit=0, flags=0)

строка Разделения случаями шаблона. Если круглые скобки получения используются в шаблоне, то текст всех групп в шаблоне также возвращается как часть получающегося списка.

Пример кода:

import re
data = re.split(r'(\D)', '2+24*48/32')
<час>

\D

, Когда флаг UNICODE не определяется, \D, соответствует любому символу нецифры; это эквивалентно набору [^0-9].

36
ответ дан Honest Abe 27 November 2019 в 05:10
поделиться
>>> import re
>>> re.findall(r'\d+|\D+', '2+24*48/32=10')

['2', '+', '24', '*', '48', '/', '32', '=', '10']

Соответствия последовательные цифры или последовательные нецифры.

Каждое соответствие возвращается как новый элемент в списке.

В зависимости от использования, Вы, возможно, должны изменить регулярное выражение. Такой, как будто необходимо соответствовать числам десятичной точке.

>>> re.findall(r'[0-9\.]+|[^0-9\.]+', '2+24*48/32=10.1')

['2', '+', '24', '*', '48', '/', '32', '=', '10.1']
18
ответ дан molasses 27 November 2019 в 05:10
поделиться

Это похоже на проблему парсинга, и таким образом я вынужден представить решение на основе методов синтаксического анализа.

, В то время как может казаться, что Вы хотите 'разделить' эту строку, я думаю, что Вы на самом деле хотите сделать, 'маркируют' его. Токенизация или lexxing являются шагом компиляции перед парсингом. Я исправил свой исходный пример в редактировании для реализации надлежащего рекурсивного достойного синтаксического анализатора здесь. Это - самый легкий способ реализовать синтаксический анализатор вручную.

import re

patterns = [
    ('number', re.compile('\d+')),
    ('*', re.compile(r'\*')),
    ('/', re.compile(r'\/')),
    ('+', re.compile(r'\+')),
    ('-', re.compile(r'\-')),
]
whitespace = re.compile('\W+')

def tokenize(string):
    while string:

        # strip off whitespace
        m = whitespace.match(string)
        if m:
            string = string[m.end():]

        for tokentype, pattern in patterns:
            m = pattern.match(string)
            if m:
                yield tokentype, m.group(0)
                string = string[m.end():]

def parseNumber(tokens):
    tokentype, literal = tokens.pop(0)
    assert tokentype == 'number'
    return int(literal)

def parseMultiplication(tokens):
    product = parseNumber(tokens)
    while tokens and tokens[0][0] in ('*', '/'):
        tokentype, literal = tokens.pop(0)
        if tokentype == '*':
            product *= parseNumber(tokens)
        elif tokentype == '/':
            product /= parseNumber(tokens)
        else:
            raise ValueError("Parse Error, unexpected %s %s" % (tokentype, literal))

    return product

def parseAddition(tokens):
    total = parseMultiplication(tokens)
    while tokens and tokens[0][0] in ('+', '-'):
        tokentype, literal = tokens.pop(0)
        if tokentype == '+':
            total += parseMultiplication(tokens)
        elif tokentype == '-':
            total -= parseMultiplication(tokens)
        else:
            raise ValueError("Parse Error, unexpected %s %s" % (tokentype, literal))

    return total

def parse(tokens):
    tokenlist = list(tokens)
    returnvalue = parseAddition(tokenlist)
    if tokenlist:
        print 'Unconsumed data', tokenlist
    return returnvalue

def main():
    string = '2+24*48/32'
    for tokentype, literal in tokenize(string):
        print tokentype, literal

    print parse(tokenize(string))

if __name__ == '__main__':
    main()

Реализацию обработки скобок оставляют как осуществление для читателя. Этот пример правильно сделает умножение перед дополнением.

18
ответ дан Jerub 27 November 2019 в 05:10
поделиться

Это - проблема парсинга, таким образом, ни один regex не разделение () не является "хорошим" решением. Используйте парсер-генератор вместо этого.

я пристально смотрел бы pyparsing. Также были некоторые достойные статьи о pyparsing в Журнал .

Python
6
ответ дан Ber 27 November 2019 в 05:10
поделиться
<блок цитирования>

с = "2+24*48/32"

p = re.compile (r' (\W +)')

p.split (s)

5
ответ дан Jiayao Yu 27 November 2019 в 05:10
поделиться

Регулярные выражения:

>>> import re
>>> splitter = re.compile(r'([+*/])')
>>> splitter.split("2+24*48/32")

можно развернуть регулярное выражение для включения любых других символов, на которых Вы хотите разделить.

4
ответ дан Cristian 27 November 2019 в 05:10
поделиться

Другое решение этого состояло бы в том, чтобы не писать калькулятор как этот в целом. Запись синтаксического анализатора RPN намного более проста, и не имеет ни одной неоднозначности свойственной от записи математики с инфиксной нотацией.

import operator, math
calc_operands = {
    '+': (2, operator.add),
    '-': (2, operator.sub),
    '*': (2, operator.mul),
    '/': (2, operator.truediv),
    '//': (2, operator.div),
    '%': (2, operator.mod),
    '^': (2, operator.pow),
    '**': (2, math.pow),
    'abs': (1, operator.abs),
    'ceil': (1, math.ceil),
    'floor': (1, math.floor),
    'round': (2, round),
    'trunc': (1, int),
    'log': (2, math.log),
    'ln': (1, math.log),
    'pi': (0, lambda: math.pi),
    'e': (0, lambda: math.e),
}

def calculate(inp):
    stack = []
    for tok in inp.split():
        if tok in self.calc_operands:
            n_pops, func = self.calc_operands[tok]
            args = [stack.pop() for x in xrange(n_pops)]
            args.reverse()
            stack.append(func(*args))
        elif '.' in tok:
            stack.append(float(tok))
        else:
            stack.append(int(tok))
    if not stack:
        raise ValueError('no items on the stack.')
    return stack.pop()
    if stack:
        raise ValueError('%d item(s) left on the stack.' % len(stack))

calculate('24 38 * 32 / 2 +')
4
ответ дан habnabit 27 November 2019 в 05:10
поделиться

я уверен, что Tim имел в виду

splitter = re.compile(r'([\D])'). 

, если Вы копируете точно, что он имеет вниз, Вы только добираетесь digits не operators.

0
ответ дан Jay D 27 November 2019 в 05:10
поделиться