我正在处理一个项目,我需要从文本文件(名为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()
答案 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]:
我个人版的marks.txt
数据文件
程序的关键,
grouper
程序无耻地改编自itertools
模块fine
docs。
文件对象可以简单地理解为返回的迭代器
文件内容逐行,所以我们从包含5的列表开始
(相同的)文件迭代器的副本,它返回我们的内容
数据文件,并传递此列表的元素(使用*
星
运算符)到zip
内置函数,它返回一个元组列表
使用每个参数中的元素,例如:
In [44]: zip(*[[1,2,3],[10,20,30]])
Out[44]: [(1, 10), (2, 20), (3, 30)]
因为zip
传递了同一文件的五个相同副本
迭代器,它构建一个包含前五行的元组列表,
我们档案的第二行,......,
但我们反过来想要它!或者,换句话说,我们想要 转置我们的元组列表。
序列序列的转座通常用a来获得 与我们刚看到的非常相似的成语......
In [45]: zip(*[(1, 10), (2, 20), (3, 30)])
Out[45]: [(1, 2, 3), (10, 20, 30)]
所有这些'\n'
换行符的问题是什么?让我们strip
他们走了......
我们的问题是我们有一个双重嵌套,比如一个列表列表 包含我们想要纠正的元素......
我们别无选择,只能用双循环解压缩元素 然后在列表中再次打包两次我们更正的,已剥离的物品 列表...
我们有一个列表列表,其元素正是我们想要的 与我们的变量名相关联,这可以在一次扫描中使用 什么叫做_sequence解包...
陈述42代表了我们问题的紧凑解决方案。很长一段时间我们都知道42就是答案,现在最终我们也知道了这个问题......
只是为了验证我们在变量中的含义是我们的结果 寻找。