使用Python 2.7,我想将以下格式的字符串转换为列表列表:
>>> value = "[[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
>>> ...
>>> result = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
我确实设法做到了这一点,但看起来很草率。
>>> value = "[[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
>>> val2 = value.replace('[[', '').replace(']]', '').split('] [')
>>> val2
['1 0 0 0', '0 1 0 0', '0 0 1 0', '0 0 0 1']
>>> val_final = [[float(x) for x in x] for x in [x.replace(' ', '') for x in val2]]
>>> val_final
[[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
是否有更好,更清洁的方法来做到更强大?
注意:我希望字符串中只有整数或浮点值(上下文:它是一个4x4矩阵,对应于3D环境中的对象位置)。
修改 替代价值可能包含如下浮点数:
>>> value = "[[9.231 -0.123 -2 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
>>> ...
>>> result = [[9.231, -0.123, -2.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
答案 0 :(得分:6)
使用标准库中的json.loads,进行一些准备(用逗号替换空格)并要求它将所有找到的整数转换为浮点数:
>>> import json
>>> value = "[[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
>>> result = json.loads(value.replace(' ', ','), parse_int=float)
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
这应该比eval更安全,并且比手动解析字符串并将其转换为正确的数据类型更容易,json解析器将为您完成。
答案 1 :(得分:4)
您可以使用replace
+ eval
:
value = "[[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
result = eval(value.replace(" ", ","))
result
#output:
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
将整数转换为浮点数:
[list(map(float, l)) for l in result] #if you're using python 2 you can remove the "list" wrapping the "map"
#output
[[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
答案 2 :(得分:1)
最灵活和可扩展的方法是实现LL(1) parser。但它需要一些工作。 这是Python 2.7中的一个粗略实现:
value = "[[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
class ParseError(ValueError):
pass
def tokenize(s):
buf = ""
while s:
if s[0] == '[':
yield s[0]
elif s[0].isalnum():
buf += s[0]
elif s[0] == ']':
if buf:
yield buf
buf = ""
yield ']'
elif s[0] == ' ':
if buf:
yield buf
buf = ""
else:
raise ParseError()
s = s[1:]
def parse_array(tokens):
if tokens[0] != '[':
raise ParseError()
tokens = tokens[1:]
elements = []
while tokens[0] != ']':
element, tokens = parse(tokens)
elements.append(element)
if not tokens:
raise ParseError()
return elements, tokens[1:]
def parse_number(tokens):
return float(tokens[0]), tokens[1:]
def parse(tokens):
if tokens[0] == '[':
return parse_array(tokens)
elif tokens[0].isalnum():
return parse_number(tokens)
else:
raise ParseError()
tokens = list(tokenize(value))
print tokens
# ['[', '[', '1', '0', '0', '0', ']', '[', '0', '1', '0', '0', ']', '[', '0', '0', '1', '0', ']', '[', '0', '0', '0', '1', ']', ']']
parsed, tokens = parse(tokens)
print parsed
# [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
注意:尚未测试所有边缘情况,但它应该知道它的外观。
我假设:
这几乎是我对这种格式做出的最宽松的假设,所以如果你不需要处理这些用例,它可能有点过分。但如果这是你需要的,那么恭喜你,你有一个LL(1)语法(换句话说,一个小语言),你需要这种解决方案。
有两个步骤:
答案 3 :(得分:1)
类似于约翰达林的回答:
您可以使用集成的Python Abstract Syntax Trees解析器,而不是使用 json 解析器:
像这样:
value = "[[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
import ast
matrix = ast.literal_eval(value.replace(" ", ", "))
print(matrix)
# -> [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
使用浮动值:
# -> [[9.231, -0.123, -2, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
要“强制”转换为浮动,只需写下:
matrix = [[float(x) for x in row] for row in matrix]
print(matrix)
# -> [[9.231, -0.123, -2.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
答案 4 :(得分:0)
value = "[[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]"
eval(value.replace(" ", ","))
输出:
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
表示返回浮点值
import numpy as np
l=np.array(eval(value.replace(" ", ",")))+0.
l.tolist()
输出
[[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]