当我输入时:
>>>tokenize('<[2{12.5 6.0}](3 -4 5)>')
我希望得到这个回复:
['<', '[', 2, '{', 12.5, 6.0, '}', ']', '(', 3, -4, 5, ')', '>']
基本上,我如何保留它以便输入将所有内容转换为列表,同时保持数字的原始值。
答案 0 :(得分:1)
你可以尝试使用tokenizer,除了像-4
这样的负数之外,它会给你几乎相同的结果,但它非常接近。
from StringIO import StringIO
import tokenize
str = '<[2{12.5 6.0}](3 -4 5)>'
tokens = tokenize.generate_tokens(StringIO(str).readline)
result = [x[1] for x in tokens]
结果如下:
['[', '2', '{', '12.5', '6.0', '}', ']', '(', '3', '-', '4', '5', ')', '>', '']
答案 1 :(得分:0)
因此,为了强制它,您可以使用list(your_string)
,但请务必确定应该将哪些内容组合在一起,并在项目中将项目附加到元素中。
其他解决方案可能有正则表达式,简单的语法库等等。并且可以说更容易理解。
编辑:对于非整数#s,您还可以注意到,当遇到这样的数字时,请继续并改变新的,已解析的标记列表的先前索引,当您到达下一个数字时,关闭,令牌等,你将在列表中创建一个全新的元素。假设您将所有内容都作为字符串放入新列表中,这里是 获取浮动内容的方法。回来了:
for i, e in enumerate(tokenized):
if e.isdigit():
tokenized[i] = int(e)
elif '.' in e:
tokenized[i] = float(e)
elif '-' in e and not '.' in e:
tokenized[i] = int(e)
最终结果是你想要的:
['<', '[', 2, '{', 12.5, 6.0, '}', ']', '(', 3, -4, 5, ')', '>']
答案 2 :(得分:0)
re.split可能就是你想要的。请参阅similar question here。
将字符串拆分为列表后,您可以使用int()
和float()
对其进行迭代并将数字成员转换为实际数字。
答案 3 :(得分:0)
PLY解决方案
tokens = (
'LT', 'GT', 'LPAREN', 'RPAREN', 'LBRACKET', 'RBRACKET', 'LBRACE', 'RBRACE',
'FLOAT', 'INTEGER',
)
t_LT = r'<'
t_GT = r'>'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_LBRACKET = r'\['
t_RBRACKET = r'\]'
t_LBRACE = r'{'
t_RBRACE = r'}'
t_ignore = r' '
def t_FLOAT(t):
r'-?\d*[.]\d+'
t.value = float(t.value)
return t
def t_INTEGER(t):
r'-?\d+'
t.value = int(t.value)
return t
def t_error(t):
raise ValueError('invalid input')
import ply.lex as lex
lex.lex()
lex.input('<[2{12.5 6.0}](3 -4 5)>')
tokens = list(iter(lex.token, None))
for t in tokens:
print repr(t.type), repr(t.value)
print '>', [t.value for t in tokens]
输出:
'LT' '<'
'LBRACKET' '['
'INTEGER' 2
'LBRACE' '{'
'FLOAT' 12.5
'FLOAT' 6.0
'RBRACE' '}'
'RBRACKET' ']'
'LPAREN' '('
'INTEGER' 3
'INTEGER' -4
'INTEGER' 5
'RPAREN' ')'
'GT' '>'
> ['<', '[', 2, '{', 12.5, 6.0, '}', ']', '(', 3, -4, 5, ')', '>']
您需要安装PLY。要安装它,只需
# pip install ply
答案 4 :(得分:0)
import re
s = '<[2{12.5 6.0}](3 -4 5)>'
p = re.compile(r"([-+]?(?:(?:\d*\.\d+)|(?:\d+\.?)))|(\S)")
conv = lambda n: float(n) if '.' in n else int(n)
[conv(m.group(1)) if m.lastindex==1 else m.group(2) for m in p.finditer(s)]
出:
['<', '[', 2, '{', 12.5, 6.0, '}', ']', '(', 3, -4, 5, ')', '>']
答案 5 :(得分:0)
import re
def tokenize(txt):
output = []
tokenized = re.split('([\<\>\[\]\{\}\(\)\s])',txt)
for t in tokenized:
if len(t.strip()) > 0:
if re.match("^\d+?\.\d+?$",t) is None:
if re.match("^[\d\-]\d*?$",t) is None:
output.append(t)
else:
output.append(int(t))
else:
output.append(float(t))
print(output)
tokenize('<[2{12.5 6.0}](3 -4 5)>')
输出:
['<', '[', 2, '{', 12.5, 6.0, '}', ']', '(', 3, -4, 5, ')', '>']
答案 6 :(得分:0)
以下是使用正则表达式的方法
import re
def tokenize(your_string):
pattern = re.compile(r'([-+]?[0-9]*\.?[0-9]+)') # float pattern
digital = re.compile(r'([-+]?[0-9]*$)')
lst = []
for item in pattern.split(your_string):
if not item.isspace(): # remove space
if pattern.match(item):
if digital.match(item):
lst.append(int(item))
else:
lst.append(float(item)) # change string to float
else:
lst.extend(list(item)) # make unmatched string to character list
return lst
print tokenize('<[2{12.5 6.0}](3 -4 5)>')
结果是
['<', '[', 2, '{', 12.5, 6.0, '}', ']', '(', 3, -4, 5, ')', '>']
答案 7 :(得分:0)
我最喜欢的工具是pyparsing。
from pyparsing import Word, ZeroOrMore, oneOf, nums
def tokenize(s):
number = Word(nums + '.' + '-')
number.setParseAction(lambda x : eval(x[0]))
punctuation = '< > [ ] ( ) { }'
lexeme = number | oneOf(punctuation) | ' '
tokenizer = ZeroOrMore(lexeme)
return tokenizer.parseString(s)
print tokenize('<[2{12.5 6.0}](3 -4 5)>')
输出:
['<', '[', 2, '{', 12.5, 6.0, '}', ']', '(', 3, -4, 5, ')', '>']
与PLY一样,您可以使用pip install pyparsing
进行安装(如果您没有,可以使用easy_install pip
安装点数)。同样在实际使用中,您可能不希望在每次调用时创建pyparsing对象,因此它们可能是全局的等等。
答案 8 :(得分:-2)
所以这是一个在python中有一个非常好的解决方案
list(my_string)
执行开头标记,但不保留您喜欢的属性:(。
因此,如果我们想要使用比必要的机械重一些的重量,那么我们就可以了。
import re
a = '<[2{12.5 6.0}](3 -4 5)>'
tokenized = [x in re.split(r'[[!"#$%&\'()*+,\-/:;<=>?@[\\\]^_`{|}~ ]]*',a)) if x!='']
#or also
tokens = [x in re.split(r'[[!"#$%&\'()*+,\-/:;<=>?@[\\\]^_`{|}~ ]]*',a)) if x]
这可以在任何语言/白板表达式中使用,而惩罚只是来自strings.punctuation,您可以自定义分隔任何,可以使用正则表达式来表示 - 这几乎就是一切。
使用re.compile预编译表达式,如果你在一个巨大的字符串上运行它 - 你会得到更好的优化。同样在某些限制条件下,您可以使用自动机来实现其中一些;)并且可以获得大量的好处