如何停止对字符串列表中的重复字母进行计数

时间:2018-08-14 15:36:25

标签: python string list

我正在尝试计算列表元素中重复字母出现的次数。

例如,给定

arr = ['capps','hat','haaah']

我列出了清单,得到了['1','0','1']

def myfunc(words):
    counter = 0 #counters dup letters in words
    len_ = len(words)-1
    for i in range(len_):
        if words[i] == words[i+1]: #if the letter ahead is the same add one
            counter+=1
    return counter

def minimalOperations(arr):
     return [*map(myfunc,arr)] #map fuc applies myfunc to element in words.

但是我的代码会输出[1,0,2]

我不确定为什么我计算过多。 谁能帮助我解决这个问题,谢谢。

6 个答案:

答案 0 :(得分:2)

使用正则表达式的更有效解决方案:

import re

def myfunc(words):
    reg_str = r"(\w)\1{1,}"
    return len(re.findall(reg_str, words))

此函数将查找包含相同字母的长度为2或更大的子字符串的数量。因此,您的示例中的“ aaa”将仅被计数一次。

对于

这样的字符串
'hhhhfafaahggaa'

输出将为4,因为同一字母的4个最大子字符串至少出现两次:'hhh','ss','gg','aa'

答案 1 :(得分:1)

您无需考虑连续有两个以上相同字符的情况。为此,您可以向后和往后看:

if (words[i] == words[i+1]) and (words[i] != words[i-1] if i != 0 else True)
    # as before

三元语句有助于循环的第一次迭代,避免将字符串的最后一个字母与第一个字母进行比较。

另一种解决方案是使用itertools.groupby并计算组的长度大于1的实例数。

arr = ['capps','hat','haaah']

from itertools import groupby

res = [sum(1 for _, j in groupby(el) if sum(1 for _ in j) > 1) for el in arr]

print(res)

[1, 0, 1]

sum(1 for _ in j)部分用于计算生成器中的项目数。也可以使用len(list(j)),尽管这需要列表构造。

答案 2 :(得分:0)

好吧,您的代码计算了重复次数,因此观察到的结果很合逻辑:

  • 您的输入是arr = ['capps','hat','haaah']
  • 在'capps'中,字母 p 被重复1次=> myfunc()返回1
  • 在“帽子”中,没有重复的字母=> myfunc()返回0
  • 在“ haaah”中,字母 a 被重复2次=> myfunc()返回2

所以最终您得到了[1,0,2]。

出于您的目的,我建议您使用正则表达式来匹配并计算每个单词中重复字母的组数。我还用列表理解取代了map()的用法,使我更容易理解:

import re

def myfunc(words):
    return len(re.findall(r'(\w)\1+', words))

def minimalOperations(arr):
    return [myfunc(a) for a in arr]

arr = ['capps','hat','haaah']
print(minimalOperations(arr))  # [1,0,1]

arr = ['cappsuul','hatppprrrrtyyy','haaah']
print(minimalOperations(arr))  # [2,3,1]

答案 3 :(得分:0)

您需要跟踪更多状态,特别是如果您现在正在查看重复项。

def myfunc(words):
    counter = 0 #counters dup letters in words
    seen = None
    len_ = len(words)-1
    for i in range(len_):
        if words[i] == words[i+1] and words[i+1] != seen: #if the letter ahead is the same add one and wasn't the first
            counter+=1
            seen = words[i]
    return counter

这将为您提供以下输出

>>> arr = ['capps','hat','haaah']
>>> map(myfunc, arr)
[1, 0, 1]

正如其他人指出的那样,您可以使用正则表达式和交易明晰性来提高性能。他们的关键是找到一个表示“两个或多个重复字符”的正则表达式,并且可能取决于您认为什么字符(例如,您如何处理重复的标点符号?)

注意:为此,“ regex”在技术上是正则表达式的扩展,因为它需要内存。

表格将为len(re.findall(regex, words))

答案 4 :(得分:0)

我会将这种问题分解为较小的部分。首先将重复项分组。 The documentation for itertools有针对此类情况的分组依据和食谱。

unique_justseen的经过稍微编辑的版本看起来像这样:

duplicates = (len(sum(1 for _ in group) for _key, group in itertools.groupby("haaah")))

并产生值:1、3、1。这些值中的任何一个大于1时,您就会重复。因此,只需数一下:

sum(n > 1 for n in duplicates)

答案 5 :(得分:0)

使用re.findall匹配2个或更多字母

>>> arr = ['capps','hat','haaah']
>>> [len(re.findall(r'(.)\1+', w)) for w in arr]
[1, 0, 1]