如何将文件读入多个列表

时间:2015-01-27 06:30:37

标签: python file-io

我正在处理一个项目,我需要从文本文件(名为marks.txt)中读取行,然后将值放入列表中。该文件是有组织的,只需读取每一行并按顺序将其添加到5个列表中的每一个,然后重复直到文件的结尾。我环顾四周,但是尽管有一对看起来很有希望,却无法找到我需要的东西。 This one有正确的想法,但只适用于单个列表,this one似乎就是答案,但它的方式比我可以使用或理解的更先进。最后,我找到了this one,这非常接近,我尝试按照答案3的方式做一些事情(与我几年前学到的相似,但它对我有用。如果有人有任何想法关于如何使这些例子的圆顶适应我的工作,这将是非常好的。对于这个项目,它不一定非常有效,只是在使用的元素方面工作和简单。这就是我现在所拥有的:

studentName= mark1=mark2= mark3=mark4 = []
dataFile=open(dataFileRaw, "r")
for line in dataFile:
    studentName.append(line) #line 1 goes to array one, line 6 goes to array 1, second value, etc
    mark1.append(line) #line 2 goes to array two
    mark2.append(line) #line 3 goes to array three
    mark3.append(line) #line 4 goes to array four
    mark4.append(line) #line 5 goes to array five
dataFile.close()

4 个答案:

答案 0 :(得分:3)

studentName= mark1=mark2= mark3=mark4 = []不会做你想要的。它创建一个列表并将其绑定到多个名称。因此,如果您修改studentName,修改将复制到mark1,mark2等。请参阅List of lists changes reflected across sublists unexpectedly

但是这里有一些代码使用列表列表来正确收集数据。它使用.strip()去除领先&从每行数据尾随空白(包括换行符)。它还使用with关键字,因此您无需显式关闭文件。

marks = [[] for _ in range(5)]

with open(dataFileRaw, "r") as dataFile:
    for i, line in enumerate(dataFile):
        marks[i % 5].append(line.strip())

enumerate()是一个内置函数,它将可迭代对象作为其第一个参数,将可选的起始编号作为其第二个参数。它返回一个新的可迭代对象,它产生一对值(以元组的形式),其中第一个值是一个count,第二个值是原始可迭代对象的下一个元素。

来自help(enumerate)

  

枚举(iterable [,start]) - >索引的迭代器,可迭代的值

     

返回枚举对象。 iterable必须是另一个对象   支持迭代。枚举对象产生包含a的对   count(从开始,默认为零)和由...产生的值   可迭代的参数。枚举对于获取索引列表很有用:

(0, seq[0]), (1, seq[1]), (2, seq[2]), ...

看一些例子可能会有所帮助:

for i,c in enumerate('qwerty'):    
    print i, c

<强>输出

0 q
1 w
2 e
3 r
4 t
5 y

我们还可以向start提供enumerate()参数,例如

seq = ['one', 'two', 'three']
for i, c in enumerate(seq, 1):
    print i, c

<强>输出

1 one
2 two
3 three

%运算符是模运算符。当我们将整数a % b除以整数a时,b得到余数。例如,

for i in range(12):
    print i % 4

<强>输出

0
1
2
3
0
1
2
3
0
1
2
3

%enumerate()放在一起让我们可以做这件事:

for i, c in enumerate('_abcdefghij'):
    print i%5, c

<强>输出

0 _
1 a
2 b
3 c
4 d
0 e
1 f
2 g
3 h
4 i
0 j

你现在明白了什么

for i, line in enumerate(dataFile):
    marks[i % 5].append(line.strip())

确实

答案 1 :(得分:1)

您遇到的问题是您实际上还没有从dataFileRaw读取数据,您只需使用open()实例化该文件。您必须确保通过以下内容读取文件中的所有数据:

dataFromFile = dataFile.read()

这会将所有数据作为字符串提取到dataFile变量中。关于这一点的好处是,之后,您可以通过拆分新行转义字符\ n(在文本编辑器中按Enter键时自动添加),将此dataFile简单地拆分为列表。

dataFromFile = dataFromFile.split("\n")[:-1]

我最后在[:-1]中添加的原因是因为如果你用\ n结束文本文件中的每一行(如果你使用了输入则自动在文件中)它会导致最后一个元素列表为空,并且您不想处理此数据,因此[: - 1]表示我们只对从索引0(包括0)到最后一个元素(独占)的数据范围感兴趣。简单地说,我们删除最后一个列表元素。

从那里你只需切换for循环来迭代dataFromFile而不是dataFile。

答案 2 :(得分:0)

试试这个,这会从你的文件中创建一个行元组,然后根据你的喜好从元组中创建一个字符串列表:

lines = tuple(open("marks.txt", 'r'))
list1, list2, list3, list4, list5 = [], [], [], [], []
i, linesCount = 0, len(lines)

while (i < linesCount):
    list1.append(lines[i].rstrip())
    i += 1
    if (i < linesCount):
        list2.append(lines[i].rstrip())
        i += 1
    if (i < linesCount):
        list3.append(lines[i].rstrip())
        i += 1
    if (i < linesCount):
        list4.append(lines[i].rstrip())
        i += 1
    if (i < linesCount):
        list5.append(lines[i].rstrip())
        i += 1

print list1, list2, list3, list4, list5

答案 3 :(得分:0)

答案

s, g1, g2, g3, g4 = [[line.strip() for line in group_of_lines] for group_of_lines in zip(*zip(*[open('marks.txt')]*5))]

我如何得出答案

ipython shell的提示符开始:

In [38]: cat marks.txt
s1
g11
g12
g13
g14
s2
g21
g22
g23
g24
s3
g31
g32
g33
g34

In [39]: zip(*[open('marks.txt')]*5)
Out[39]: 
[('s1\n', 'g11\n', 'g12\n', 'g13\n', 'g14\n'),
 ('s2\n', 'g21\n', 'g22\n', 'g23\n', 'g24\n'),
 ('s3\n', 'g31\n', 'g32\n', 'g33\n', 'g34\n')]

In [40]: zip(*zip(*[open('marks.txt')]*5))
Out[40]: 
[('s1\n', 's2\n', 's3\n'),
 ('g11\n', 'g21\n', 'g31\n'),
 ('g12\n', 'g22\n', 'g32\n'),
 ('g13\n', 'g23\n', 'g33\n'),
 ('g14\n', 'g24\n', 'g34\n')]

In [41]: [[line.strip() for line in group_of_lines] for group_of_lines in zip(*zip(*[open('marks.txt')]*5))]
Out[41]: 
[['s1', 's2', 's3'],
 ['g11', 'g21', 'g31'],
 ['g12', 'g22', 'g32'],
 ['g13', 'g23', 'g33'],
 ['g14', 'g24', 'g34']]

In [42]: s, g1, g2, g3, g4 = [[line.strip() for line in group_of_lines] for group_of_lines in zip(*zip(*[open('marks.txt')]*5))]

In [43]: print '\n'.join(map(str,(s,g1,g2,g3,g4)))
['s1', 's2', 's3']
['g11', 'g21', 'g31']
['g12', 'g22', 'g32']
['g13', 'g23', 'g33']
['g14', 'g24', 'g34']

In [44]:

&#34的逐行评论;我如何得出答案&#34;

[38]

我个人版的marks.txt数据文件

[39]

程序的关键, grouper 程序无耻地改编自itertools模块fine docs

文件对象可以简单地理解为返回的迭代器 文件内容逐行,所以我们从包含5的列表开始 (相同的)文件迭代器的副本,它返回我们的内容 数据文件,并传递此列表的元素(使用*星 运算符)到zip内置函数,它返回一个元组列表 使用每个参数中的元素,例如:

In [44]: zip(*[[1,2,3],[10,20,30]])
Out[44]: [(1, 10), (2, 20), (3, 30)]

因为zip传递了同一文件的五个相同副本 迭代器,它构建一个包含前五行的元组列表, 我们档案的第二行,......,

[40]

但我们反过来想要它!或者,换句话说,我们想要 转置我们的元组列表。

序列序列的转座通常用a来获得 与我们刚看到的非常相似的成语......

In [45]: zip(*[(1, 10), (2, 20), (3, 30)])
Out[45]: [(1, 2, 3), (10, 20, 30)]

[41]

所有这些'\n'换行符的问题是什么?让我们strip 他们走了......

我们的问题是我们有一个双重嵌套,比如一个列表列表 包含我们想要纠正的元素......

我们别无选择,只能用双循环解压缩元素 然后在列表中再次打包两次我们更正的,已剥离的物品 列表...

[42]

我们有一个列表列表,其元素正是我们想要的 与我们的变量名相关联,这可以在一次扫描中使用 什么叫做_sequence解包...

陈述42代表了我们问题的紧凑解决方案。很长一段时间我们都知道42就是答案,现在最终我们也知道了这个问题......

[43]

只是为了验证我们在变量中的含义是我们的结果 寻找。