如何将一个string分割成一个列表?

如果我有这个string:

2 + 24 *32分之48

什么是创build这个列表最有效的方法:

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

恰好碰巧你要分割的令牌已经是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'] 

你可以使用从re模块split

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

由模式发生的分割string。 如果在模式中使用捕获括号,则模式中所有组的文本也会作为结果列表的一部分返回。

示例代码:

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

\ d

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

这看起来像一个parsing问题,因此我不得不提出一个基于parsing技术的解决scheme。

虽然看起来你想“分割”这个string,但我认为你真正想要做的是“标记”它。 Tokenization或Lexxing是parsing之前的编译步骤。 我已经修改了我原来的例子,在这里实现了一个适当的recursion裁剪。 这是手工实现parsing器的最简单方法。

 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() 

括号的处理的实施留给读者作为练习。 这个例子将在添加之前正确地进行乘法运算。

 >>> import re >>> re.findall(r'\d+|\D+', '2+24*48/32=10') ['2', '+', '24', '*', '48', '/', '32', '=', '10'] 

匹配连续的数字或连续的非数字。

每个匹配作为列表中的新元素返回。

根据使用情况,您可能需要更改正则expression式。 例如,如果您需要与小数点匹配的数字。

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

这是一个parsing问题,所以正则expression式不是split()是“好”的解决scheme。 使用parsing器生成器来代替。

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

常用expression:

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

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

s =“2 + 24 * 48/32”

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

p.split(S)

解决这个问题的另一个办法是避免写一个像这样的计算器。 编写一个RPNparsing器要简单得多,而且没有用中缀表示法编写math的固有含糊之处。

 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 +') 
 >>> import re >>> my_string = "2+24*48/32" >>> my_list = re.findall(r"-?\d+|\S", my_string) >>> print my_list ['2', '+', '24', '*', '48', '/', '32'] 

这将做的伎俩。 以前我遇到过这样的问题。

为什么不使用SymPy ? 它应该做你想要实现的。

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

我个人会直接利用exec的Python的mathfunction:

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

我确定蒂姆的意思

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

如果你确切地复制了他的下落,你只能得到digits而不是operators