【问题标题】:Python - making counters, making loops?Python - 制作计数器,制作循环?
【发布时间】:2010-06-04 12:11:08
【问题描述】:

我在下面的一段代码中遇到了一些问题:

输入:li 是一个嵌套列表,如下:

li = [['>0123456789 mouse gene 1\n', 'ATGTTGGGTT/CTTAGTTG\n', 'ATGGGGTTCCT/A\n'],   ['>9876543210 mouse gene 2\n', 'ATTTGGTTTCCT\n', 'ATTCAATTTTAAGGGGGGGG\n']]

使用下面的函数,在整个子列表中存在的“/”个数大于 1 的情况下,我想要的输出只是“>”后面的第 2 到第 9 位。

相反,我的代码为所有条目提供了数字。此外,它给了他们多次。因此,我认为我的计数器和 for 循环有问题。这个我不太清楚。

任何帮助,不胜感激。

import os

cwd = os.getcwd()


def func_one():
    outp = open('something.txt', 'w')       #output file
    li = []
    for i in os.listdir(cwd):           
        if i.endswith('.ext'):
            inp = open(i, 'r').readlines()
            li.append(inp)
    count = 0
    lis = []
    for i in li:
        for j in i:
            for k in j[1:]          #ignore first entry in sublist
                if k == '/':
                    count += 1
                if count > 1:
                    lis.append(i[0][1:10])      
                    next_func(lis, outp)

谢谢, S :-)

【问题讨论】:

    标签: python loops counter


    【解决方案1】:

    您的缩进可能有误,您应该在for j in i 循环中检查count > 1,而不是在检查j[1:] 中每个字符的循环中。

    另外,这里有一个更简单的方法来做同样的事情:

    def count_slashes(items):
        return sum(item.count('/') for item in items)
    
    for item in li:
        if count_slashes(item[1:]) > 1:
            print item[0][1:10]
    

    或者,如果您需要列表中的 ID:

    result = [item[0][1:10] for item in li if count_slashes(item[1:]) > 1]
    

    Python list comprehensionsgenerator expressions 是非常强大的工具,尝试学习如何使用它们,因为它可以让你的生活变得更简单。上面的count_slashes 函数使用了生成器表达式,而我最后的代码 sn-p 使用列表推导以一种简洁明了的方式构造了结果列表。

    【讨论】:

    • Python 一次又一次地让我惊讶,有些事情是多么容易。很好的答案 +1
    【解决方案2】:

    Tamás 提出了一个很好的解决方案,尽管它使用的编码风格与您完全不同。不过,由于您的问题是“我在使用下面的一段代码时遇到了一些问题”,我认为还需要更多的东西。

    以后如何避免这些问题

    您在从“我想我知道如何编写此代码”到拥有实际工作代码的方法中犯了几个错误。

    您为变量使用了无意义的名称,这使得您几乎无法理解您的代码,包括您自己。 “但我知道每个变量的含义”的想法显然是错误的,否则您将设法自己解决这个问题。请注意,在我修复您的代码的地方,描述和讨论您的代码是多么困难。

    你试图一次解决整个问题,而不是把它分解成小块。编写一次只做一件事的小函数或代码片段。对于你工作的每一件作品,把它做好并测试它以确保它是正确的。然后继续写可能使用你已经得到的片段的其他片段。我说的是“碎片”,但通常是指函数、方法或类。

    修复代码

    这是你要求的,没有其他人这样做。

    您需要将count = 0 行移到for i in li: 行之后(适当缩进)。这将重置每个子列表的计数器。其次,一旦你附加到lis 并运行你的next_func,你需要打破for k in j[1:] 循环和包含for j in i: 循环。

    这是一个工作代码示例(没有 next_func,但您可以将其添加到 append 旁边):

    >>> li = [['>0123456789 mouse gene 1\n', 'ATGTTGGGTT/CTTAGTTG\n', 'ATGGGGTTCCT/A\n'],   ['>9876543210 mouse gene 2\n', 'ATTTGGTTTCCT\n', 'ATTCAATTTTAAGGGGGGGG\n']]
    >>> lis = []
    >>> for i in li:
            count = 0
            for j in i:
                break_out = False
                for k in j[1:]:
                    if k == '/':
                        count += 1
                    if count > 1:
                        lis.append(i[0][1:10])
                        break_out = True
                        break
                if break_out:
                    break
    
    >>> lis
    ['012345678']
    

    重写代码以使其可读

    这是为了让你明白我在回答开头的意思。

    >>> def count_slashes(gene):
        "count the number of '/' character in the DNA sequences of the gene."
        count = 0
        dna_sequences = gene[1:]
        for sequence in dna_sequences:
            count += sequence.count('/')
        return count
    >>> def get_gene_name(gene):
        "get the name of the gene"
        gene_title_line = gene[0]
        gene_name = gene_title_line[1:10]
        return gene_name
    >>> genes = [['>0123456789 mouse gene 1\n', 'ATGTTGGGTT/CTTAGTTG\n', 'ATGGGGTTCCT/A\n'],   ['>9876543210 mouse gene 2\n', 'ATTTGGTTTCCT\n', 'ATTCAATTTTAAGGGGGGGG\n']]
    >>> results = []
    >>> for gene in genes:
            if count_slashes(gene) > 1:
                results.append(get_gene_name(gene))
    
    >>> results
    ['012345678']
    >>> 
    

    【讨论】:

    • sum(seq.count('/') for seq in gene[1:]) 可以很好地完成这项工作。
    • 很好的答案 - 如果可以的话,我会多次投票。
    【解决方案3】:
    import itertools
    import glob
    
    lis = []
    with open('output.txt', 'w') as outfile:
        for file in glob.iglob('*.ext'):
            content = open(file).read()
            if content.partition('\n')[2].count('/') > 1:
                lis.append(content[1:10])
                next_func(lis, outfile)
    

    您对所有条目进行数字化的原因是因为您没有重置计数器。

    【讨论】:

    • 您能告诉我如何重置计数器吗?这一直发生在我身上,所以我通常通过一个函数运行所有内容以删除重复项。谢谢!
    • @seafoid:您需要将count = 0 移动到for in li: 行之后,但最好使用我的代码,它更高效,并且不需要所有那些嵌套循环。
    • @SilentGhost - 谢谢!如果每个子列表的第一个字符串中存在计数“/”,是否可以修改您的代码以排除计数?
    • 它不是来自我。感谢您的帮助!
    • 哎呀,这不是反对票。有人刚刚收回了他的赞成票。
    猜你喜欢
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 2017-10-19
    • 2016-09-09
    • 1970-01-01
    相关资源
    最近更新 更多