将文件中所有奇数行求和的 Pythonic 方法

Posted

技术标签:

【中文标题】将文件中所有奇数行求和的 Pythonic 方法【英文标题】:Pythonic method to sum all the odd-numbered lines in a file 【发布时间】:2013-04-15 18:55:04 【问题描述】:

我正在学习 Python 是为了参加研究生院的编程分班考试,这实际上是我编写的第一个小脚本来感受它。我的背景主要是 C# 和 php,但我不能在测试中使用任何一种语言。

我的测试脚本读入下面的文本文件 (test_file1.txt)。偶数行包含样本大小,奇数行包含样本中每个测试的“结果”。 EOF 标记为 0。我想读入文件,输出样本量,并对每个测试的结果求和。您将如何使用 Python 执行此任务?我觉得我试图强迫 python 像 PHP 或 C# 一样,根据我的研究,我猜想有非常“Python”的方式来做这些事情。

test_file1.txt:

3
13 15 18
5 
19 52 87 55 1
4
11 8 63 4
2
99 3
0

我的简单脚本:

file = open("test_file1.txt", "r")

i=0
for line in file:
    if i % 2 == 0:
        #num is even
        if line == '0':
            #EOF
            print 'End of experiment'   
    else:
        #num is odd
        numList = line.split( )
        numList = [int(x) for x in numList]
        print 'Sample size: ' + str(len(numList)) + ' Results: ' + str(sum(numList))
    i += 1

file.close()

我的结果:

Sample size: 3 Results: 46
Sample size: 5 Results: 214
Sample size: 4 Results: 86
Sample size: 2 Results: 102
End of experiment

谢谢!

【问题讨论】:

所以这是一个测试?还有代码审查? 使用enumerate给行编号:for i, line in enumerate(file) @sr2222,是的,差不多(好吧,我凭空想出了一个示例测试问题)。我想比较一下在没有 Python 知识的情况下我是如何处理这个问题的,与知道 Python 的人相比。 【参考方案1】:

将文件用作迭代器,然后使用iterators.islice() 获取每一行:

from itertools import islice

with open("test_file1.txt", "r") as f:
   for line in islice(f, 1, None, 2):
       nums = [int(n) for n in line.split()]
       print 'Sample size:   Results: '.format(len(nums), sum(nums))

islice(f, 1, None, 2) 跳过第一行 (start=1),然后遍历所有行 (stop=None),每隔一行返回 (step=2)。

这适用于你扔给它的任何文件大小;它不需要比内部迭代器缓冲区更多的内存。

测试文件的输出:

Sample size: 3  Results: 46
Sample size: 5  Results: 214
Sample size: 4  Results: 86
Sample size: 2  Results: 102

【讨论】:

itertools 是第三方库还是 Python 内置的? 它是一个标准库;它与 Python 一起提供。我在答案中链接到该方法的文档。【参考方案2】:

你可以这样做:

with open("test_file1.txt", "r") as inf:
    lines = inf.readlines()
    for l in lines[1::2]:  # read only alternating lines
        numList = map(int, line.split())
        print "Sample size:", len(numList), "Results:", sum(numList)

【讨论】:

我看到@MartijnPieters 的反对意见很多。但我想知道:1)这有关系吗? 2) 当内存不是问题时,islice() 方法是否更快? 除非您绝对确定输入文件总是很小,否则最好避免一次将整个文件读入内存。 islice() 完全用 C 实现,因此使用它的开销很小,最重要的是,它创建列表的副本。 lines[1::2] 必须首先创建一个新列表,其中包含所有奇数行,比文件的初始列表增加 50% 的内存使用量,并且创建该列表也需要时间。 不将整个文件读入 mem 是我试图避免使用我的简单解决方案做的一件事,但只要你先检查文件大小以确保它是 【参考方案3】:

这样的事情怎么样,相当 Pythonic 恕我直言:

with open('test.txt') as fh:
    for i, line in enumerate(fh):
        if i % 2:
            nums = map(int, line.split())
            print 'Sample size: %d, Results: %d' % (len(nums), sum(nums))
        elif line == '0':
            print 'End of experiment'

【讨论】:

我喜欢这个解决方案。使用内置函数 (enumerate()) 和简单构造 (模数),因此不需要了解 itertools.islice()【参考方案4】:

我不确定pythonic 的人是如何找到这个的,但我发现zip、ma​​p 和reduce 是一种非常方便的方式,可以以紧凑的方式执行此操作。但是,它可能有点混淆。

with open("test.txt") as fd:                                                                                                           
   lines = [map(int, s.strip().split()) for s in fd.readlines()]                                                                      
   print "\n".join("Sample Size: %d \t Results: %d"%tuple(map(sum,(d[0],d[1])))                                                       
                   for d in zip(lines, lines[1:], range(len(lines)))                                                                  
                   if d[2] % 2 == 0)        

【讨论】:

tuple 不需要顺便说一句,你可以简单地使用(...) 来代替。 如果你把 (...) 放在它周围,它不会转换为元组,它只会阻止执行顺序,即作为括号。这将导致字符串格式错误,因为格式正在查找数字并且格式的输入将是一个列表:"%d"%(map(...)) 将导致错误。

以上是关于将文件中所有奇数行求和的 Pythonic 方法的主要内容,如果未能解决你的问题,请参考以下文章

谁能告诉我excel表格中如何将数字按奇数和偶数依次排列

将CSV文件数据读取为命名元组行的pythonic方法是啥?

1~100所有奇数求和

求和一系列数字

奇数求和

C# 如何撰写将一个Datatable的所有奇数行提取出来生成一个表,所有偶数行提取出来生成一个表?