我正在尝试实现频繁的单词伪代码。根据一个样本数据集,我应该返回2个频繁的单词,但我只返回第一个。 这是伪代码:
FrequentWords(Text, k)
FrequentPatterns <-- an emty set
for i <-- 0 to |Text| - k
Pattern <-- the k-mer Text(i,k)
Count(i) <-- PatternCount(Text,Pattern)
maxCount <-- max value in array Count
for i <-- 0 to |Text| - k
if Count(i) = maxCount
add Text(i,k) to FrequentPatterns
remove duplicates from FrequentPatterns
return FrequentPatterns
这是我的实施:
def PatternCount(Text, Pattern):
Count = 0
for i in range(0, (len(Text) - len(Pattern) + 1)):
if Text[i:i+len(Pattern)] == Pattern:
Count = Count + 1
return Count
def FrequentWords(Text, k):
FrequentPatterns = [0]
Count = [0] * (len(Text) - k + 1)
for i in range(0, (len(Text) - k + 1)):
Pattern = Text[i:i+k]
Count[i] = PatternCount(Text, Pattern)
maxCount = max(Count)
for i in range(0, (len(Text) - k + 1)):
if Count[i] == maxCount:
FrequentPatterns = Text[i:i + k]
return FrequentPatterns
以下是示例数据集: ACGTTGCATGTCGCATGATGCATGAGAGCT 4
我应该从代码返回: CATG GCAT
但我只是第一个 - CATG。请帮忙。
答案 0 :(得分:1)
s = 'ACGTTGCATGTCGCATGATGCATGAGAGCT'
length = 4
我会用字典来累积结果。使用切片提取 next 字;在字典中为该单词的值添加一个;然后删除字符串中的第一个字符;循环,而字符串中有一个单词。
result = {}
while len(s) >= length:
word = s[:length]
result[word] = result.get(word, 0) + 1
s = s[1:]
您可能可以使用collections.Counter or collections.defaultdict作为该位。如果单词不能重叠,请从字符串前面删除length
个字符。保持过程简单会导致从循环底部的字符串中删除字符时效率低下。除非数据很长或者过程执行了很多次,否则它不重要。
然后找到具有最高频率
的单词most = max(result.values())
frequent = []
for key, value in results:
if value == most:
frequent.append(key)
#frequent = [key for key, value in result.items() if value == most]
从itertools recipe借用你可以创建一个产生所需长度的单词的迭代器
def n_wise(iterable, n=2):
'''s -> (s0,s1), (s1,s2), (s2, s3), ... for n=2'''
tees = itertools.tee(iterable, n)
for i, thing in enumerate(tees, 1):
for _ in range(i):
next(thing, None)
return zip(*tees)
程序的计数部分将变为
words = n_wise(s, length)
result = {}
for word in words:
result[word] = result.get(word, 0) + 1
result
中的密钥将是元组,例如('C', 'A', 'T', 'G')
但可以使用''.join(('C', 'A', 'T', 'G'))
重新构建它们。
答案 1 :(得分:1)
你应该考虑使用列表推导。
def pattern_count(text, pattern):
matches = ([x for x in range(len(text) - len(pattern) + 1) if pattern in text[x:len(pattern) + x]])
return len(matches)
def frequent_words(text, k):
counts = [pattern_count(text, text[x:x + k]) for x in range(len(text) - k)]
return set([text[x:x + k] for x in range(len(text) - k) if counts[x] == max(counts)])
pattern_count 将解析模式的字符串。我们拼接文本字符数组,因此我们可以检查该部分是否包含该模式。这允许我们在结果中包含重叠条目。例如,
pattern_count(ABABA,ABA) - &gt;结果是2,而不是1。
print(pattern_count("BABBASDCABCBABDDASDBBCASDBAB", "BAB"))
[0] 3
frequent_words 采用相同的文本,但不是模式,我们给它一个int,表示模式应该有多长。一旦我们得到满足我们的字符 k 要求的每个模式的出现次数列表,我们就会通过获取最频繁出现的条目来过滤它。最后,为了删除任何重复项,我们将列表转换为一个本身可以防止重复条目的哈希集,从而返回一个只有唯一值的集合。
测试:
print(frequent_words("BABBASDCABCBABDDASDBBCASDBAB", 3))
[0] {'BAB', 'ASD'}
希望这对你有用。
答案 2 :(得分:0)
改为使用dict
:
def FrequentWords(Text, k):
FrequentPatterns = {}
for i in range(0, (len(Text) - k + 1)):
Pattern = Text[i:i+k]
if Pattern in FrequentPatterns:
FrequentPatterns[Pattern] += 1
else:
FrequentPatterns.update({Pattern: 1})
for x in sorted(FrequentPatterns.items(), key=lambda m: m[1], reverse=True):
print(x)