【问题标题】:Counting the total number of lines except the ones that start with a special character计算除以特殊字符开头的行之外的总行数
【发布时间】:2021-12-10 14:54:46
【问题描述】:

我想从文本文件中获取原子数。这个文本文件以几行标题开头,有时它可能会添加一些额外的信息行,这些信息行也以特殊字符开头。示例文本文件如下所示:

% site-data vn=3.0
#                        pos
Ga        0.0000000   0.0000000   0.0000000
As        0.2500000   0.2500000   0.2500000 

我的方法是计算以特殊字符开头的行数和行数,所以这是我的尝试:

def get_atom_number():
    count = 0
    with open(sitefile,'r') as site:
        x = len(site.readlines())
        for line in site.readlines():
            if '#' in line or '%' in line:
                count +=1
return x-count

这个函数的问题是,定义了 x(总行数)后,计数器(以特殊字符开头的行数)返回 0。如果我删除该行,它就可以工作。现在,我可以将这两个分成两个函数,但我相信这应该可以正常工作,并且我想知道我做错了什么。

【问题讨论】:

    标签: python counting


    【解决方案1】:

    if '#' in line or '%' in line: 将检查字符是否在行中的任何位置。请改用startswith·

    if line.startswith(('#', '%')):
    

    现在,关于计数方法,你也可以只在行以字符开头时才增加计数器,这样你就不需要提前知道总行数和不需要消耗所有的行:

    if not line.startswith(('#', '%')):
        counter += 1
    

    那你可以直接打印最后的计数器

    完整代码:

    def get_atom_number():
        count = 0
        with open(sitefile,'r') as site:
            for line in site.readlines():
                if not line.startswith(('#', '%')):
                    count +=1
        return count
    

    【讨论】:

    • 你也可以使用count = sum(1 for line in site if not line.startswith(('#', '%')))
    【解决方案2】:

    您面临的问题是.readlines() 在执行时会消耗整个文件。如果你再次调用它,什么都不会出现,因为它已经在文件的末尾了。

    解决方案是首先将site.readlines() 分配给一个变量,然后更改以下两行以引用该变量。这样,您只需调用一次。

    def get_atom_number():
        count = 0
        with open(sitefile,'r') as site:
            lines = site.readlines()
            x = len(lines)
            for line in lines:
                if '#' in line or '%' in line:
                    count +=1
        return x - count
    

    【讨论】:

    • 感谢您的回答,您完全正确。这让我想知道,这是一种记忆友好的方法吗?如果我正在处理大文件,这仍然是一种合乎逻辑的方式吗?
    • 更节省内存的方法是使用@mozway 的答案,除了迭代site 而不是site.readlines()。这样一来,您根本不会将整个 .readlines() 读入内存,一次只能读一行。
    【解决方案3】:

    第 4 行代码中的第一次调用 site.readlines() 将文件光标移动到末尾。所以第 5 行的第二次调用 site.readlines() 只会得到一个空列表。 您可以尝试下面的代码,它将调用site.readlines() 的结果保存到变量lines。我认为它可以解决您的问题。

    def get_atom_number():
        count = 0
        with open(sitefile,'r') as site:
            lines = site.readlines()
            x = len(lines)
            for line in lines:
                if '#' in line or '%' in line:
                    count +=1
        return x - count
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案4】:

    改用readline

    def get_atom_number():
        count = 0
        with open(sitefile,'r') as site:
            for line in site.readline():
                if '#' not in line and '%' not in line:
                    count +=1
        return count
    

    作为mozway的回答,startswith是一个更好的解决方案,所以代码可以是这样的:

    from pathlib import Path
    from typing import Union
    
    IGNORE = ('#', '%')
    
    def get_atom_number(filename: str = sitefile, ignore_chars: Union[str, tuple] = IGNORE) -> int:
        '''Count how many lines in filename that not startswith ignore_chars'''
        return len([1 for i in Path(filename).read_text().splitlines() if not i.startswith(ignore_chars)])
    

    【讨论】:

    • 我相信这会计算字符数,而不是行数。
    • @user175924 函数可以是一种线条样式。
    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 2015-12-17
    相关资源
    最近更新 更多