嵌套Python列表解析构建列表的列表

问题描述:

我是一个python newb,并且遇到了嵌套列表解析的困难。我试图编写一些代码来读取文件,并为每一行的每个字符构造一个列表。嵌套Python列表解析构建列表的列表

所以如果该文件包含

xxxcd 
cdcdjkhjasld 
asdasdxasda 

结果列表将是:

[
[ 'X', 'X', 'X', 'C', 'd'] 'd','c','d','j','k','h','j','a','s','1','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

对于简单性和可读性有很多要说的。虽然你可能能够通过嵌套理解获得相同的效果,但也可能最终导致无意模糊处理。 – 2009-12-30 20:03:58

+3

另外,不要有一个名为'file'的变量。我知道'file'和'open'是同义词,但是如果你需要测试'isinstance(f,file)',你会后悔的。也许称它为'filename'?名字为'list'的变量也是如此。 – 2009-12-30 20:10:04

这应该有所帮助(你可能需要玩弄它去剥离换行符或格式你想要的东西,但基本的思路应该工作):

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

任何人都可以解释这种形式的内在理解是如何工作的吗?我一直在为此而苦苦挣扎。 – 2016-01-20 18:44:24

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

+1,但我宁愿将每个条目作为字符串保留在列表中。由于字符串可以被编入索引,因此您仍然可以将它视为二维字符数组。仅当OP计划对行进行更改时,才需要“list(...)”部分。 – 2009-12-30 20:07:29

这里是列表理解的一个水平。

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()重新加入列表回到一个字符串,但为什么不把它作为一个字符串?)

首先,你可以结合line.strip()与外的环上()的一部分,这样的:

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

然后,你可以将字符迭代到列表c中不理解,但它不会更短或更清晰。最巧妙的方法做,你在那里做什么是这样的:

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)这会有点失败的目的,但有时是必要的。

>>> 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']] 

在你的情况,你可以使用list构造函数来处理内部循环,并使用列表理解为外环。喜欢的东西:

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

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

列表内涵在功能上等同于:字符的字符串和列表之间

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

唯一真正显著的区别是,字符串是不可变的。您可以按照列出的方式遍历和切分字符串。将字符串作为字符串处理会更方便,因为它们支持字符串方法,而列表不支持字符串方法。

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

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

当我需要操作字符串在data为可变的名单,我会使用list将它们转换,并join把他们回来,例如:

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

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