嵌套python list comprehensions来构造一个列表列表

时间:2009-12-30 20:00:16

标签: python list-comprehension

我是一个python newb,并且在查看嵌套列表推导方面遇到了麻烦。我正在尝试编写一些代码来读取文件,并为每一行的每个字符构建一个列表。

所以如果文件包含

xxxcd
cdcdjkhjasld
asdasdxasda

结果列表为:

[
[ 'X', 'X', 'X', 'C', 'd']
[ 'C', 'd', 'C', 'd', 'J', 'K', 'H', 'J', 'A', 'S', 'L', 'd'] <登记/> [ '一个', 'S', 'd', 'A', 'S', 'd', 'X', 'A', 'S', 'd', 'A']
]

我编写了以下代码,但是它有效,但我有一种唠叨的感觉,我应该能够用更少的代码行编写嵌套列表理解。任何建议将不胜感激。

data = []
f = open(file,'r')
for line in f:
    line = line.strip().upper()
    list = []
    for c in line:
        list.append(c)
    data.append(list)

7 个答案:

答案 0 :(得分:18)

这应该有所帮助(你可能不得不玩它来剥离新行或按照你想要的格式化它,但基本的想法应该有效):

f = open(r"temp.txt")
[[c for c in line] for line in f]

答案 1 :(得分:3)

在您的情况下,您可以使用list构造函数来处理内部循环并使用外部循环的列表理解。类似的东西:

f = open(file)
data = [list(line.strip().upper()) for line in f]

给定一个字符串作为输入,列表构造函数将创建一个列表,其中字符串的每个字符都是列表中的单个元素。

列表理解在功能上等同于:

data = []
for line in f:
    data.append(list(line.strip().upper()))

答案 2 :(得分:2)

这是列表理解的一个层次。

data = []
f = open(file,'r')

for line in f:
    data.append([ch for ch in line.strip().upper()])

但我们可以一次完成整个事情:

f = open(file, 'rt')
data = [list(line.strip().upper()) for line in f]

这是使用list()将字符串转换为单字符字符串列表。我们也可以使用嵌套列表推导,并将open()内联:

data = [[ch for ch in line.strip().upper()] for line in open(file, 'rt')]

但是,在这一点上,我认为列表理解是减少,使其不易被发现。

对于复杂的处理,例如列表中的列表,您可能希望对外层使用for循环,对内循环使用列表推导。

另外,正如Chris Lutz在评论中所说,在这种情况下,确实没有理由将每一行明确地分成字符列表;您始终可以将字符串视为列表,并且可以将字符串方法与字符串一起使用,但不能将字符串方法与列表一起使用。 (好吧,您可以使用''.join()将列表重新加入字符串,但为什么不将其保留为字符串?)

答案 3 :(得分:1)

data = [list(line.strip().upper()) for line in open(file,'r')]

答案 4 :(得分:1)

字符串和字符列表之间唯一真正重要的区别是字符串是不可变的。您可以像列出一样迭代并切片字符串。将字符串作为字符串处理会更方便,因为它们支持字符串方法,而列表则不支持。

因此,对于大多数应用程序,我不会费心将data中的项目转换为列表;我只是这样做:

data = [line.strip() for line in open(filename, 'r')]

当我需要将data中的字符串作为可变列表进行操作时,我会使用list来转换它们,并使用join将它们放回去,例如:

data[2] = ''.join(sorted(list(data[2])))

当然,如果要对这些字符串进行修改,请修改它们,然后继续将它们存储为列表。

答案 5 :(得分:0)

首先,你可以将line.strip()。upper()部分与你的外部for循环结合起来,如下所示:

for line in [l.strip().upper() for l in f]:
    # do stuff

然后你可以将字符的迭代变成列表理解,但它不会更短或更清晰。做你做的最好的方法是:

list(someString)

因此你可以这样做:

data = [list(l.strip().upper()) for l in f]

我不知道它是否表达了你的意图。错误处理也是一个问题,如果在途中出现问题,整个表达式将会死亡。


如果您不需要将整个文件和所有行存储在内存中,则可以将其作为生成器表达式。这在处理大型文件时非常有用,您只需要一次处理一个块。生成器表达式使用括​​号,如下所示:

data = (list(l.strip().upper()) for l in f)

data将成为一个生成器,它为文件中的每一行运行表达式,但只有在迭代它时才会运行;将其与列表理解进行比较,列表理解将在内存中创建一个巨大的列表。请注意,data不是列表,而是生成器,更多是C ++中的迭代器或C#中的IEnumerator的亲属。

可以轻松地将生成器输入列表:list(someGenerator)这会在一定程度上破坏目的但有时是必要的。

答案 6 :(得分:0)

>>> f = file('teste.txt')
>>> print map(lambda x: [c for c in x][:-1], f)
[['x', 'x', 'x', 'c', 'd'], ['c', 'd', 'c', 'd', 'j', 'k', 'h', 'j', 'a', 's', 'l', 'd'], ['a', 's', 'd', 'a', 's', 'd', 'x', 'a', 's', 'd']]