【问题标题】:Calculating the average of numbers in txt file计算txt文件中数字的平均值
【发布时间】:2021-02-02 12:09:16
【问题描述】:

我正在尝试在 python 中编写一个函数,它读取文件,提取文件中冒号后的数字,并返回数字的平均值

(平均值的简单公式 => 数字的总和 / 数字的数量)

文件看起来像:

数字1:7

#more 可以添加

thenumber2: 4(#yes冒号后有空格)

应忽略以“#”开头的行。

到目前为止我的代码:

import os

def get_average_n(path):


s = ""
t = 0
v = 0

if not os.path.exists(path):
    return None

if os.stat(path).st_size == 0:
    return 0.0

else:
    p = open(path, "r")

    content = p.readlines()

    for line in content:
        if line.startswith("#"):
            continue

        elif not line.startswith("#"):
            x = line.find(":")
            s += line[x + 1:]
            h = s.replace("\n", "")

            for c in h:
                if c.isdigit():
                    t += float(c)
                    v += 1
                    avg = round(t / v, 2)

return avg
print(get_average_n("file.txt"))

在 casementionet (fat) 中输出应该是 5.5 但我得到错误的输出,我真的找不到问题。它返回 6.25 而不是 5.5。

【问题讨论】:

  • 不缩进for c in h:。它应该与elif...对齐
  • 仍然得到相同的输出,
  • 无关:为什么要检查if line.startswith('#'),然后检查elif not line.startswith('#')?如果超出if,您知道line 不以# 开头
  • 谢谢,我没有意识到这一点。现在它工作正常,除非数字是浮点数,thenumber1: 3.25 #comment thenumbe2r:5 -> 给我 3.75 但应该是 4.125

标签: python-3.x function file


【解决方案1】:

为了澄清我的评论。

我修正了缩进,我得到了正确的结果。

ss = '''
thenumber1:7

#more could be added

thenumber2: 4
'''.strip()

with open('file.txt','w') as f: f.write(ss)

#################

import os

def get_average_n(path):
    s = ""
    t = 0
    v = 0

    if not os.path.exists(path):
        return None

    if os.stat(path).st_size == 0:
        return 0.0

    else:
        p = open(path, "r")
        content = p.readlines()

    for line in content:
        if line.startswith("#"):
            continue
        elif not line.startswith("#"):
            x = line.find(":")
            s += line[x + 1:]
            h = s.replace("\n", "")

    for c in h:
        if c.isdigit():
            t += float(c)
            v += 1
            avg = round(t / v, 2)

    return avg
    
print(get_average_n("file.txt"))  # 5.5

------- 为了更简洁地解析文件,试试这个:

def get_average_n(path):
    numlst = []

    if not os.path.exists(path):
        return None

    if os.stat(path).st_size == 0:
        return 0.0

    else:
        with open(path, "r") as p:
           content = p.readlines()

    for line in content:
        if not line.startswith("#") and line.find(":") >= 0:
            numlst.append(float(line.split(':')[1].strip()))

    avg = sum(numlst)/len(numlst)

    return avg

【讨论】:

  • 非常感谢,但它似乎不适用于像 3.25 这样的数字,你能帮我解决这个问题吗? .例如:如果数字 1:3.25 和数字 2:5,它应该返回 4.00 但我得到 3.75
  • 我将数字替换为 3.25 和 5。结果是 4.125,这是正确的。
  • 你是对的,非常感谢,我又试了一次。但我不明白为什么浮点数不适用于第一个解决方案。只有“更清洁的方法”适用于花车。
  • 您正在使用isdigit 来检查号码中的每个数字。小数 . 不是数字,因此会被跳过。您的代码仅适用于一位数整数。
  • 有没有办法识别小数点?除了按照您的方式更改代码。
【解决方案2】:

我添加了使用正则表达式的解决方案。我喜欢常规,因为它们具有出色的查找、搜索和替换功能。见下文。

注意:将lines.py & file.txt 复制到目录并运行。你会得到4.75,即(7 + 4 + 3.25) / 3

参考链接:Python Regex instantly replace groupsHow to extract a floating number from a string

» file.txt

thenumber1:7

#more could be added

thenumber2: 4 

thenumber1: 3.25

» lines.py

import os, re

def get_average_n(path):
    if not os.path.exists(path):
        return 0.0

    if os.stat(path).st_size == 0:
        return 0.0
    else:
        total, avg, count = 0.0, 0.0, 0
        regex = r"(.*):\s*(\d+(\.\d+)?)(.*)\s*" # Regex to match interger & 3.25, 4.56 kind of floats
        p = open(path, "r")
        content = p.readlines()

        for line in content:
            if line.strip().startswith('#'):
                continue

            num_s = re.sub(regex, r'\2', line).strip()
            if num_s:
                total += float(num_s)
                count += 1

        if count:
            avg = total / count

    return avg


if __name__ == "__main__":
    print(get_average_n('file.txt'))

» 最后使用python lines.py 运行。

谢谢。

【讨论】:

  • 感谢您的帮助,但现在我需要有关角落案例的帮助。 thenumber1: 或 thenumber:2 可以是浮点数,例如:thenumber1: 3.25 #morespace thenumber2: 5
  • 然后您需要更改正则表达式以匹配浮点数和整数。我已经更新了我的答案。根据您给定的示例,将r"(.*):\s*(\d+)(.*)\s*" 更改为r"(.*):\s*(\d+(\.\d+)?)(.*)\s*" 并更新file.txt。因此,如果您需要更多匹配项,那么只需像这样更新您的正则表达式即可。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多