5

我是一个 python 新手,在理解嵌套列表理解时遇到了麻烦。我正在尝试编写一些代码来读取文件并为每行的每个字符构造一个列表。

所以如果文件包含

xxxcd
cdcdjkhjasld
asdasdxasda

结果列表将是:

[
['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','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)
4

7 回答 7

19

这应该会有所帮助(您可能必须使用它来去除换行符或根据需要对其进行格式化,但基本想法应该有效):

f = open(r"temp.txt")
[[c for c in line] for line in f]
于 2009-12-30T20:06:25.653 回答
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()))
于 2009-12-30T20:07:41.017 回答
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()将列表重新加入字符串,但为什么不将其保留为字符串?)

于 2009-12-30T20:05:54.750 回答
1
data = [list(line.strip().upper()) for line in open(file,'r')]
于 2009-12-30T20:05:38.717 回答
1

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

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

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

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

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

当然,如果您对这些字符串所做的只是修改它们,那么继续,将它们存储为列表。

于 2009-12-30T20:29:54.950 回答
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)这会在某种程度上破坏目的,但有时是必要的。

于 2009-12-30T20:06:33.173 回答
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']]
于 2009-12-30T20:07:33.560 回答