如果我有这个字符串:
2 + 24 *32分之48
创建此列表的最有效方法是什么:
['2','+','24','*','48','/','32']
答案 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