如何将字符串拆分为列表?

时间:2008-09-17 23:17:12

标签: python string list split

如果我有这个字符串:

  

2 + 24 *32分之48

创建此列表的最有效方法是什么:

  

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

11 个答案:

答案 0 :(得分:50)

恰好,您想要拆分的令牌已经是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']

答案 1 :(得分:36)

您可以使用split模块中的re

re.split(pattern, string, maxsplit=0, flags=0)

  

按照模式的出现拆分字符串。如果捕获括号   在模式中使用,然后模式中的所有组的文本   也作为结果列表的一部分返回。

示例代码:

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

\ d

  

如果未指定UNICODE标志,则\ D匹配任何非数字   字符;这相当于集[^ 0-9]。

答案 2 :(得分:18)

这看起来像是一个解析问题,因此我不得不提出一种基于解析技术的解决方案。

虽然看起来你想要“拆分”这个字符串,但我认为你真正想要做的就是“标记”它。标记化或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()

支架处理的实施留给读者练习。此示例将在添加之前正确执行乘法。

答案 3 :(得分:18)

>>> 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']

答案 4 :(得分:6)

这是一个解析问题,因此正则表达式和split()都不是“好”的解决方案。请改用解析器生成器。

我会密切关注pyparsing。在Python Magazine中也有一些关于pyparsing的体面文章。

答案 5 :(得分:5)

  
    
      

s =“2 + 24 * 48/32”

             

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

             

p.split(S)

    
  

答案 6 :(得分:4)

正则表达式:

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

您可以展开正则表达式以包含要拆分的任何其他字符。

答案 7 :(得分:4)

另一个解决方案是避免完全编写这样的计算器。编写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 +')

答案 8 :(得分:1)

>>> import re
>>> my_string = "2+24*48/32"
>>> my_list = re.findall(r"-?\d+|\S", my_string)
>>> print my_list

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

这样就可以了。我以前遇到过这种问题。

答案 9 :(得分:0)

我确定蒂姆意味着

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

如果您确切地复制了他的内容,则只能获得digits而不是operators

答案 10 :(得分:0)

这并没有完全回答这个问题,但我相信它能解决你想要达到的目标。我会将其添加为评论,但我还没有这样做的许可。

我个人会直接使用exec:

来利用Python的数学功能
  

表达式=“2 + 24 * 48/32”
   exec “result =”+表达
  打印结果
  38