我想知道,如果你用Python打开一个文本文件。然后你想搜索包含许多字母的单词。
假设您输入要搜索的6个不同字母(a,b,c,d,e,f)。 你想找到至少3个字母的单词。 每个字母只能出现一个单词。 字母'a'总是必须包含。
对于这种特定类型的搜索,代码应该如何?
答案 0 :(得分:3)
让我们看看......
return [x for x in document.split()
if 'a' in x and sum((1 if y in 'abcdef' else 0 for y in x)) >= 3]
没有参数的 split
充当"字"函数,拆分任何空格并删除不包含字符的单词。然后你检查字母' a'在这个词里面。如果' a'在单词中,您使用生成器表达式,该表达式遍历单词中的每个字母。如果字母在可用字母串内,则返回1,该值对总和有贡献。否则,它返回0.然后如果总和是3或更大,它保持它。使用生成器而不是列表推导,因为sum将接受任何可迭代的内容,并且它会阻止必须创建临时列表(减少内存开销)。
由于使用in
(在字符串上应该有O(n)时间),它没有最佳的访问时间,但这通常不是一个很大的问题除非数据集很大。您可以优化一点,将字符串打包成一个集合,并且常量' abcdef'很容易就成了一套。我只是不想破坏漂亮的衬垫。
编辑:哦,为了改善if
部分(效率低下的部分)的时间,你可以把它分成一个迭代字符串一次的函数,如果符合条件就返回True 。我会这样做,但它毁了我的一个班轮。
def is_valid(word, chars):
count = 0
for x in word:
if x in chars:
count += 1
chars.remove(x)
return count >= 3 and 'a' not in chars
def parse_document(document):
return [x for x in document.split() if is_valid(x, set('abcdef'))]
这个在现实世界的数据集上不应该有任何性能问题。
答案 1 :(得分:2)
如果我不得不写这个,我会怎么做:
我有一个函数,给定一个单词,将检查它是否满足条件并返回一个布尔标志。
然后我会有一些代码会迭代文件中的所有单词,将每个单词显示给函数,并打印出函数返回的那些单词True
。
答案 2 :(得分:0)
words = 'fubar cadre obsequious xray'
def find_words(src, required=[], letters=[], min_match=3):
required = set(required)
letters = set(letters)
words = ((word, set(word)) for word in src.split())
words = (word for word in words if word[1].issuperset(required))
words = (word for word in words if len(word[1].intersection(letters)) >= min_match)
words = (word[0] for word in words)
return words
w = find_words(words, required=['a'], letters=['a', 'b', 'c', 'd', 'e', 'f'])
print list(w)
编辑1:我也没有仔细阅读这些要求。确保单词仅包含1个有效字母的实例。
from collections import Counter
def valid(word, letters, min_match):
"""At least min_match, no more than one of any letter"""
c = 0
count = Counter(word)
for letter in letters:
char_count = count.get(letter, 0)
if char_count > 1:
return False
elif char_count == 1:
c += 1
if c == min_match:
return True
return True
def find_words(srcfile, required=[], letters=[], min_match=3):
required = set(required)
words = (word for word in srcfile.split())
words = (word for word in words if set(word).issuperset(required))
words = (word for word in words if valid(word, letters, min_match))
return words
答案 3 :(得分:0)
我同意aix的总体计划,但它可能比“设计模式”更为普遍,而且我不确定它会给你带来多大的影响,因为它归结为“,找出一种方法来检查是什么你想找到然后检查你需要检查的一切。“
有关如何找到您想要找到的内容的建议:您已经进入了算法研究的最基本领域之一。虽然LCS(最长公共子串)被更好地覆盖,但你也可以找到遏制的好例子。我见过的关于这个主题的最严格的讨论是在Google cs wonk的网站上:http://neil.fraser.name。他有一个名为diff-match-patch的东西,它以许多不同的语言发布和优化,包括python,可以在这里下载: http://code.google.com/p/google-diff-match-patch/
如果你想更多地了解python和算法,magnus hetland写了一本关于python算法的好书,他的网站在字符串匹配和模糊字符串匹配等方面有一些例子,包括levenshtein距离简单易懂的格式。 (google for magnus hetland,我不记得地址)。
在标准库中,您可以查看difflib,它提供了许多方法来评估字符串的相似性。你正在寻找不相同的遏制,但它是非常相关的,你可能会根据你的需要制作一组你可以比较的候选词。
或者你可以使用python,Counter的新增功能,并将你正在测试的单词重建为字符串列表,然后为每个测试字母创建一个需要1或更多计数的函数。
最后,关于aix方法的第二部分,'然后将它应用于你想要测试的所有内容,'我建议你看一下itertools。如果你有任何效率约束,你将需要使用生成器和aix提出的测试可以使用itertools.ifilter在python中最有效地执行。您的函数对于要保留的值以及内置函数bool返回True。所以你可以做itertools.ifilter(bool,test_iterable),它将返回所有成功的值。
祝你好运