所以给了“针”和“这里有针但不是这个针干草堆”
我写了
def find_needle(n,h):
count = 0
words = h.split(" ")
for word in words:
if word == n:
count += 1
return count
这是O(n),但想知道是否有更好的方法?也许根本不使用拆分?
如何为此案例编写测试以检查它是否处理所有边缘情况?
答案 0 :(得分:9)
我认为这可能与O(n)
相反(因为你需要至少迭代一次字符串)。你可以做一些优化。
我假设您要匹配" 整个单词",例如查找foo
应该匹配如下:
foo and foo, or foobar and not foo.
^^^ ^^^ ^^^
仅仅基于太空的夹板不会起作用,因为:
>>> 'foo and foo, or foobar and not foo.'.split(' ')
['foo', 'and', 'foo,', 'or', 'foobar', 'and', 'not', 'foo.']
# ^ ^
这是re
module派上用场的地方,可以让你建立迷人的条件。例如,正则表达式中的\b
表示:
匹配空字符串,但仅匹配单词的开头或结尾。 单词被定义为Unicode字母数字或下划线字符的序列,因此单词的结尾由空格或非字母数字 ,非下划线Unicode字符表示。请注意,正式地,
\b
被定义为\w
和\W
字符之间的边界(反之亦然),或\w
与字符串的开头/结尾之间的边界。这意味着r'\bfoo\b'
匹配'foo'
,'foo.'
,'(foo)'
,'bar foo baz'
但不匹配'foobar'
或'foo3'
。
因此r'\bfoo\b'
仅匹配整个字foo
。也不要忘记使用re.escape()
:
>>> re.escape('foo.bar+')
'foo\\.bar\\+'
>>> r'\b{}\b'.format(re.escape('foo.bar+'))
'\\bfoo\\.bar\\+\\b'
现在您只需使用re.finditer()
扫描字符串即可。基于文档:
返回一个迭代器,在字符串中的RE模式的所有非重叠匹配上产生匹配对象。从左到右扫描字符串,并按找到的顺序返回匹配项。结果中包含空匹配,除非它们触及另一场比赛的开头。
我认为匹配是动态生成的 ,所以它们不必一次在内存中(这可能会与大字符串派上用场,许多匹配项目)。最后只计算它们:
>>> r = re.compile(r'\bfoo\b')
>>> it = r.finditer('foo and foo, or foobar and not foo.')
>>> sum(1 for _ in it)
3
答案 1 :(得分:5)
这并未解决复杂性问题,但简化了代码:
def find_needle(n,h):
return h.split().count(n)
答案 2 :(得分:4)
您可以使用Counter
from collections import Counter
def find_needle(n,h):
return Counter(h.split())[n]
即:
n = "portugal"
h = 'lobito programmer from portugal hello fromportugal portugal'
print find_needle(n,h)
输出:
2
答案 3 :(得分:3)
实际上,当你说O(n)你忘记了匹配第一个字母后,你必须匹配剩余的那个(从针到句子匹配n,然后匹配e,然后是下一个e。 ..)您实际上是在尝试复制grep的功能,因此您可以查看grep算法。你可以通过构建有限状态机来做得很好。有许多链接可以帮助您,您可以从How does grep run so fast?
开始答案 4 :(得分:1)
这仍然是O(n),但它使用了re模块和python的生成器表达式的强大功能。
import re
def find_needle(n,h):
g = re.finditer(r'\b%s\b'%n, h) # use regex word boundaries
return sum(1 for _ in g) # return the length of the iterator
对于相对较大的“干草堆”,应该使用比.split少得多的内存。
请注意,这与OP中的代码并不完全相同,因为它不仅会找到' needle'还有针,'并且'针。'它找不到针头'虽然。
答案 5 :(得分:0)
为了保证在大海捞针中找到针,你需要检查每一块干草,直到找到针。无论如何,这都是O(n),一个紧张的下限。
答案 6 :(得分:0)
def find_needle(haystack):
for item in haystack:
if item == 'needle':
haystack.append(item)
return 'found the needle at position ' + str(haystack.index(item))
答案 7 :(得分:0)
这是我的。
// Text
$search = 'bar soap';
$parsedSearch = explode(' ', 'bar soap');
// Create pattern
$patterns = [];
$patterns[] = $search; // bar soap
$patterns[] = $parsedSearch[1] . ' ' . $parsedSearch[0]; // soap bar
$patterns[] = $parsedSearch[0]; //bar
$patterns[] = $parsedSearch[1]; //soap
// Set Query
$query = "select `inventories`.*, MATCH (title, short_description, brand, long_description, inventory_code, product_code) AGAINST ('bar soap' IN BOOLEAN MODE) as score from `inventories` where MATCH (title, short_description, brand, long_description, inventory_code, product_code) AGAINST ('bar soap' IN BOOLEAN MODE) order by field(`score`," . implode(',', $patterns) . ")";
return $query;
在这里,我们仅使用内置的count方法来计算大海捞针中的针数。