将列表列表中的元组字符串转换为Python中的列表项

时间:2013-02-24 02:24:06

标签: python eval abstract-syntax-tree

列表l包含由两种类型的列表组成的项目,第一列是由字符串组成的可接受列表,第二列是包含字符串的元组字符串。第二种类型的所有列表都具有相同的长度 - 2.我想将第二种类型的所有列表转换为与第一种类型相同的约定,如下所示(l2是更新列表)。

编辑:我应该澄清我正在处理的实际列表中有两个以上的项目,所以我需要一个循环函数来适应这个。

l = [["('N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '')", "('61060', '61060')"], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]

l2 = [['N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '', '61060', '61060'], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]

到目前为止,以下内容仅限于我:

from csv import reader
from cStringIO import StringIO

l2 = []

for i in l:
    if len(i) == 2:
        filestr = StringIO(i[0] + i[1])
        csv_reader = reader(filestr, quotechar="'")
        for t in csv_reader:
            l2.append(t)
    else:
        l2.append(i)

4 个答案:

答案 0 :(得分:2)

你可以使用ast:

>>> import ast
>>> l = [["('N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '')", "('61060', '61060')"], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
>>> l2=[e for e in ast.literal_eval(l[0][0])]
>>> l2+=[e for e in ast.literal_eval(l[0][1])]
>>> l2=[l2]
>>> l2.append(l[1])

>>> l2
[['N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '', '61060', '61060'], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]

如您所知,eval存在一些真正的安全问题。 ast非常安全,因为它只能生成Python基础数据结构。

答案 1 :(得分:1)

如果,且仅当,您信任输入,您可以评估它:

l2 = eval(l[0][0])

我不完全理解整个输入的结构,所以我无法帮助你完成所有输入的循环。

答案 2 :(得分:1)

这不是csv问题,因为你没有csv。 (实际上你困惑了我一段时间,因为我试图想象一下csv文件的样子!)

  1. 建立一个“测试”列表是否需要规范化(is_tuple_string_row函数如下)。
  2. 使用ast.literal_eval将元组字符串安全地转换为实际元组。
  3. 使用chain.from_iterable将所有元组合并为一个序列。
  4. 以下完整代码实现为生成器normalized_list()

    l = [["('N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '')", "('61060', '61060')"], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
    
    l2 = [['N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '', '61060', '61060'], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
    
    import ast
    from itertools import imap, chain
    
    
    def is_tuple_string_row(L):
        """Return whether list L is a list of strings containing tuples"""
        return len(L)==2 and all(s.startswith("('") and s.endswith("')") for s in L)
    
    
    def normalized_list(L):
        """Yield lists in sequence L as lists of strings
    
        Normalizes a list of strings of tuples down to a simple list of strings
        """
        for item in L:
            if is_tuple_string_row(item):
                yield list(chain.from_iterable(imap(ast.literal_eval, item)))
            else:
                yield item
    
    
    # You can iterate efficiently
    for item in normalized_list(l):
        print item
    
    # or you can put the whole thing to a single new list
    aslist = list(normalized_list(l))
    
    # verify results
    assert aslist == l2
    

答案 3 :(得分:0)

我建议使用Lists而不是Tuples,然后在必要时索引列表/子列表/列表的子列表以实现您想要的效果。

另一个想法是制作一个你想要的结构类。放置切片列表的方法。看起来你想要一个元组中的前9个项目,而最后两个项目需要一个单独的元组。这也是将它们分开的好方法。