在python中计算非空白和行长度的总和

时间:2015-02-09 04:09:52

标签: function python-3.x functional-programming tuples

尝试创建一个带有文件名的函数,它返回一个2元组,其中包含该程序中非空行的数量,以及所有这些行的长度之和。这是我目前的计划。我做了一个尝试,得到了以下代码:

def code_metric(file_name):
    with open(file_name) as f:
        lines = f.read().splitlines()
    char_count = sum(map(len,(map(str.strip,filter(None,lines)))))
    return len(lines), char_count

我应该使用功能映射,过滤和减少。我曾经问过这个问题并改进了我的答案,但它仍然给我一个错误。以下是该问题的上一版本的链接:

Old program code

当我运行具有以下内容的文件cmtest.py

import prompt,math

x = prompt.for_int('Enter x')
print(x,'!=',math.factorial(x),sep='')

结果应该是

(3,85)

但我一直在接受:

(4,85)

另一个要测试的文件colltaz.py例如:

结果应该是:

(73, 2856)
我持续得到:

(59, 2796)

以下是collat​​z.py文件的链接:

Collatz.py file link 任何人都可以帮我纠正代码。对python来说相当新,任何帮助都会很棒。

1 个答案:

答案 0 :(得分:2)

试试这个:

def code_metric(file_name):
    with open(file_name) as f:
        lines = [line.rstrip() for line in f.readlines()]
    nonblanklines = [line for line in lines if line]
    return len(nonblanklines), sum(len(line) for line in nonblanklines)

示例:

>>> code_metric('collatz.py')
(73, 2856)

>>> code_metric('cmtest.py')
(3, 85)

讨论

我只能通过删除尾部换行符和尾随行尾的空白来实现collatz.py的预期结果。这是在这一步骤中完成的:

lines = [line.rstrip() for line in f.readlines()]

下一步是删除空行:

nonblanklines = [line for line in lines if line]

我们想要返回非空白行的数量:

len(nonblanklines)

我们还希望返回非空行上的字符总数:

sum(len(line) for line in nonblanklines)

大文件的替代版本

此版本不需要一次将文件保存在内存中:

def code_metric2(file_name):
    with open(file_name) as f:
        lengths = [len(line) for line in (line.rstrip() for line in f.readlines()) if line]
    return len(lengths), sum(lengths)

使用reduce

的备用版本

Python的创建者,Guido van Rossum,wrote this关于reduce内置:

  

所以现在减少()。这实际上是我一直非常讨厌的那个,   因为,除了几个涉及+或*的例子,几乎每次都有   我看到一个带有非平凡函数参数的reduce()调用,我需要   抓住笔和纸,以图表实际上是什么   在我理解reduce()应该做什么之前的函数。所以   在我看来,reduce()的适用性几乎受到限制   关联运算符,在所有其他情况下,最好写出来   积累循环明确。

因此reduceno longer a builtin in python3。但是,为了兼容性,它仍然可以在functools模块中使用。以下代码reduce如何用于此特定问题:

from functools import reduce

def code_metric3(file_name):
    with open(file_name) as f:
        lengths = [len(line) for line in (line.rstrip() for line in f.readlines()) if line]
    return len(lengths), reduce(lambda x, y: x+y, lengths)

这是另一个版本,它更多地使用了reduce

from functools import reduce
def code_metric4(file_name):
    def fn(prior, line):
        nlines, length = prior
        line = line.rstrip()
        if line:
            nlines += 1
            length += len(line)
        return nlines, length
    with open(file_name) as f:
        nlines, length = reduce(fn, f.readlines(), (0, 0))
    return nlines, length