我有一些字符串
str = 'kkyykykyyk'
我想知道在这个字符串中出现“kyy”和“ky”的次数。 但是,如果某些内容像本例中那样重叠,那么我只需要计算更长的子字符串。
Mu当前解决方案看起来像这样
k = str.count('kyy')
y = (str.count('ky') - str.count('kyy'))
print(k, y) # solution: 'kyy' two times AND 'ky' one time
这个问题是否有更短或更“蟒蛇”的方法?
答案 0 :(得分:4)
一种方法是使用正则表达式并使用?
运算符来检查字符串中是否出现额外的y。
也就是说,我们发现ky
的出现,并检查下一个值是y
是否发生我们接受其他我们不
>>> import re
>>> st = 'kkyykykyyk'
>>> re.findall(r'kyy?',st)
['kyy', 'ky', 'kyy']
>>> re.findall(r'kyy?',st).count('kyy')
2
>>> re.findall(r'kyy?',st).count('ky')
1
答案 1 :(得分:2)
这是一种方法。拆分'kyy'
。结果数组的长度 - 1是'kyy'
出现的次数。然后通过再次连接和分割来计算结果数组中'ky'
的出现次数。
正如@Windygound指出的那样,如果字符串中没有出现'kyy'
(没有要拆分)或者字符串中有其他字母(即{{1} }})。这是一个解决方法:
'kkyykyakyyk'
另外,请避免将变量# original example
s = 'kkyykykyyk'
print(s.split('kyy'))
#['k', 'ky', 'k']
# solution
arr = s.split('kyy')
print(len(arr)-1, len(" ".join(arr).split('ky'))-1)
命名为内置类型。
速度测试结果表明OP的代码实际上是最快的。可以通过在注释中使用@ wim的建议来重新使用变量str
来改进它。
定义功能
k
制作一些随机测试数据
# OP's solution
def count_ky(s):
k = s.count('kyy')
y = (s.count('ky') - s.count('kyy'))
return (k, y)
# OP's solution with @wim's suggestion
def count_ky2(s):
k = s.count('kyy')
y = (s.count('ky') - k)
return (k, y)
def count_ky_nathan(s):
k, y = 0, 0
for place in range(len(s)):
if s[place:].startswith('kyy'):
k += 1
elif s[place:].startswith('ky'):
y += 1
return (k, y)
def count_ky_pault(s):
arr = s.split('kyy')
k = len(arr)-1
y = len(" ".join(arr).split('ky'))-1
return (k, y)
def count_ky_albin(s):
k = re.findall(r'kyy?',s).count('kyy')
y = re.findall(r'kyy?',s).count('ky')
return (k, y)
验证结果匹配
import random
import string
N = 1000
# pick from the letters k, y, and x
test_words = [
''.join(random.choice(['k', 'y', 'x']) for _ in range(random.randint(10,30)))
for _ in range(N)
]
速度测试
我遗漏了@ Nathan的第三个解决方案(怪异的一个),因为它没有正确的计数。
test_funcs = [count_ky, count_ky2, count_ky_nathan, count_ky_pault, count_ky_albin,
count_ky_nathan2]
for tf in test_funcs:
print reduce(lambda x, y: [x[i]+y[i] for i in range(2)], [tf(s) for s in test_words])
#[687, 1424]
#[687, 1424]
#[687, 1424]
#[687, 1424]
#[687, 1424]
#[687, 1424]
答案 2 :(得分:0)
为了计算较长的子串实例,我会用一些在我想要查看的数据中无效的字符替换子字符串。然后重复每个连续的子串。
string = 'kkyykykyyk'
substrings = {'kyy': 0, 'ky': 0}
for sub, val in substrings.items():
index = string.find(sub)
while index != -1:
val += 1
string = string[:index] + '###' + string[index + len(sub):]
index = string.find(sub)
substrings[sub] = val
可以将字符串和字典打印为
k#########k
{'kyy': 2, 'ky': 1}
答案 3 :(得分:0)
尝试简洁易读而不聪明,因为对我来说,#pythonic"非常关注可读性:
s = 'kkyykykyyk'
k, y = 0, 0
for place in range(len(s)):
if s[place:].startswith('kyy'):
k += 1
elif s[place:].startswith('ky'):
y += 1
对于聪明和简短,我喜欢@ pault的分裂和计数方法的这种变化:
parts = s.split('kyy')
k = len(parts) - 1
y = sum(p.count('ky') for p in parts)
最后一个奇怪的,只是为了好玩:
nokyy = s.replace('kyy', ' ') # replace with ' ' so we don't create new matches!
noky = nokyy.replace('ky', '')
k = (len(s) - len(nokyy))//2
y = (len(nokyy) - len(noky))//2