首页 > 解决方案 > 计数包含文件中存在的每个子字符串的行

问题描述

所以我编写了这段代码来在字符串中查找子字符串(长度k)。我希望它检查 466 个字符串(从通过打开的文件中pc),如果存在子字符串,则添加1到子字符串字典proteinCDict中,因此基本上计算子字符串出现的序列数。显然它不起作用:

import operator

proteinCDict = {}
for i in range(0, 466):
    record = []
    pc.readline()
    sequence = pc.readline()
    for j in range(0, len(sequence)-k):
        if((sequence[j:j+k] in proteinCDict) and\
           (sequence[j:j+k] not in record)):
            record.append(sequence[j:j+k])
            proteinCDict[sequence[j:j+k]] += 1
        else:
            record.append(sequence[j:j+k])
            proteinCDict[sequence[j:j+k]] = 1

proteinCDict =  sorted(proteinCDict.items(), key=operator.itemgetter(1))
print(proteinCDict)

我面临的问题是通过k=7时的一个特殊情况来说明的,出现频率最高的子串低于k=8时的子串。这不应该是这样,因为在 k=8 中频率最高的子串可以分成两个长度为 7 的子串。那么我哪里出错了?

编辑:每条备用线都是一个空格,因此我打了readline()2 次电话。

标签: pythonpython-3.x

解决方案


首先,对您的代码的一些评论:

  • 我看到的主要问题是,通过循环range(0, len(sequence)-k),您正在跳过子序列sequence[len(sequence)-k:]

  • 如果你要打开一个文件,你应该使用一个with语句。

  • range您可以直接遍历文件对象以获取其行,而不是使用 a 。

  • 对于与计数相关的任何事情,acollections.Counter可能更适合。

  • 为了跟踪在单行上看到了哪些子序列,aset比 a 更适合数据结构,list因为它允许恒定时间查找。

以下解决方案使用 a Counter,然后您可以使用Counter.most_common按出现次数对子序列进行排序。

代码

import collections

def count_in_file(filename, k):
    counter = collections.Counter()

    with open(filename, 'r') as f:
        for line in f:
            line = line.strip()

            line_sequences = set(line[i:i+k] for i in range(len(line) + 1 - k))

            for seq in line_sequences:
                counter[seq] += 1

    return counter

counter = count_in_file('test_file.txt', 3)

print(counter.most_common())

测试文件

ABCABC

BCA

输出

[('BCA', 2), ('CAB', 1), ('ABC', 1)]

推荐阅读