将列表的LARGE字符串表示转换为列表Python 3

时间:2016-01-01 14:38:26

标签: python python-3.x memory

我有一个(大量)列表表示为字符串(不是这样,这只是一个例子)

"['A', 'B', 'C']"

我需要将其设为列表类型:

['A', 'B', 'C']

但如果我这样做:

list("['A', 'B', 'C']")
显然我会得到:

['[', "'", 'A', "'", ',', ' ', "'", 'B', "'", ',', ' ', "'", 'C', "'", ']']

目前我正在使用:

ast.literal_eval("['A', 'B', 'C']")

除了我的程序正在处理的列表很大,字符串是数百万字节(测试字符串超过400万个字符)。所以每当我尝试运行它时,我的ast.literal_eval()都会返回一个MemoryError。

因此,我需要一种方法(它不必是pythonic,优雅甚至特别有效)将这些巨大的字符串放入列表而不返回错误。

6 个答案:

答案 0 :(得分:3)

输入数据格式并不完全标准,解析起来不方便,特别是因为它很大。根据数据的来源,您应该开始将其保存在真实数据库中,或者考虑如何使其成为可解析的JSON。例如,如果我们在当前样本输入中用双引号替换单引号,我们可以用json解析它:

>>> import json
>>> s = "['A', 'B', 'C']"
>>> json.loads(s.replace("'", '"'))
[u'A', u'B', u'C']

然后,一旦数据是JSON,它就是一个不同且更常见的问题。您可以使用增量解析器之一,如ijson或事件驱动的yajl,以避免内存错误。

答案 1 :(得分:3)

您可以尝试使用基于迭代器接口和itertools模块的延迟解析。

您可以使用例如itertools.takewhile

def lazy_to_list(input_string):
    iterable = iter(input_string)
    next(iterable)  # skip [
    l = []
    while True:
        value = ''.join(itertools.takewhile(lambda c: c != ',', iterable))
        if not value:
            break
        if value.endswith("]"):
            value = value.rstrip("]")
        l.append(eval(value))
    return l


N = 1000000
s = repr(list(range(N)))
assert lazy_to_list(s) == list(range(N))

额外的改进是从文件中延迟加载巨大的字符串(因为所有处理都是懒惰的)。显然,它会在对象表示中打破逗号(可能还有更多的原因)。

无论如何,对于定义严重的问题,它仍然是一种解决方案。根据基础数据的类型和外部要求(例如,文件应该是人可读的,而不仅仅是机器),您可以更好地使用标准序列化格式(例如jsonxml,{{3}等等。)

答案 2 :(得分:0)

很抱歉浪费你的时间,我尝试了其他一切之后找到了一个非常灵巧但有效的解决方案:

str.split("', '")

并且移除了末端括号,因为任何字符串中都没有因为它的使用方式而突然出现。我们去了。

答案 3 :(得分:0)

你可以使用真棒的YAML库(pip install pyyaml)。

>>> import yaml
>>> yaml.load("['A', 'B', 'C']")
['A', 'B', 'C']

如果您正在阅读文件,您也可以这样做:

>>> with open(myfile) as fid:
...     data = yaml.load(fid)

答案 4 :(得分:-2)

使用Python内置的eval( str )函数可能会更好运。

eval("['A', 'B', 'C']")

返回一个列表对象

['A', 'B', 'C']

答案 5 :(得分:-2)

>>> import ast
>>> input = "['A', 'B', 'C']"
>>> list = ast.literal_eval(input)
>>> output = [i.strip() for i in list]
>>> type(output)
<class 'list'>
>>> output
['A', 'B', 'C']