将字符串转换为列表列表

时间:2016-08-25 15:23:23

标签: python python-2.7

使用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]]

5 个答案:

答案 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]]

注意:尚未测试所有边缘情况,但它应该知道它的外观。

我假设:

  • 数字或括号之间可以有任意数量的空格
  • 括号不需要后跟空格
  • 格式表示任何维度的jagged arrays(它们可以有不同长度的行)(它们可以任意嵌套)。

这几乎是我对这种格式做出的最宽松的假设,所以如果你不需要处理这些用例,它可能有点过分。但如果这是你需要的,那么恭喜你,你有一个LL(1)语法(换句话说,一个小语言),你需要这种解决方案。

有两个步骤:

  1. 标记化:将字符串转换为符号序列(括号,数字和其他可能的标识符)。
  2. 解析:转换表达式树中的符号序列。为此,您需要在知道如何解释以下符号(因此LL1中的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]]