Python-判断给定字符串中是否只有1个字符重复的最有效方法是什么?

时间:2018-01-31 15:58:59

标签: python algorithm collections

前一段时间遇到过一个问题,它让我想知道最好的方法是什么。

想要一个接受输入字符串并返回布尔值的方法,无论给定的字符串是否只有1个字符重复(可以重复多次)

即:' abca' - >是的,' abab' - >错,' aaaa' - >真

我的解决方案似乎有点复杂,我想知道更好的方法

#!/usr/bin/env python
import collections

def hasOnlyOneDuplicate(string):
    # turn string into a dictionary with counter and obtain a list of all the values/occurences of each letter
    values = list(collections.Counter(string).values())
    # then we remove all the numbers that are a 1
    result = filter(lambda a: a!=1, values)
    return len(result) == 1

如果给定字符串中只有1个重复字符,则剩余列表的长度应为1,对吗?否则有多个字符重复

感谢您的帮助

3 个答案:

答案 0 :(得分:2)

使用set可以轻松完成此操作。我正在使用您的示例'abca'

def hasOnlyOneDuplicate(s):
   return len(set(a for a in s if s.count(a) > 1))==1 

答案 1 :(得分:2)

另一种使用str.count()和短路欺骗计数器的方法:

def hasOnlyOneDuplicate(s):
    nDupes = 0
    for ch in set(s):
        if s.count(ch) > 1:
            nDupes += 1
        if nDupes > 1:
            return False
    return (nDupes == 1)

<强>更新

此解决方案是最快的,特别是对于长字长度:

from collections import Counter
import string
import random

def hasOnlyOneDuplicate_pault(s):
    nDupes = 0
    for ch in set(s):
        if s.count(ch) > 1:
            nDupes += 1
        if nDupes > 1:
            return False
    return (nDupes == 1)

def hasOnlyOneDuplicate_dev(s):
    x = list(s)
    if len(set([a for a in x if x.count(a) > 1]))==1: 
        return True 
    else: 
        return False

def hasOnlyOneDuplicate_john(s):
     return len([c for c,v in Counter(s).items() if v > 1]) == 1

N = 1000
test_words = [
    ''.join(random.choice(string.lowercase) for _ in range(random.randint(3,30)))
    for _ in range(N)
]

%%timeit
len([hasOnlyOneDuplicate_pault(s) for s in test_words])
# 100 loops, best of 3: 2.57 ms per loop

%%timeit
len([hasOnlyOneDuplicate_dev(s) for s in test_words])
# 100 loops, best of 3: 7.6 ms per loop

%%timeit
len([hasOnlyOneDuplicate_john(s) for s in test_words])
# 100 loops, best of 3: 9.61 ms per loop

更新2

所有发布的答案都比OP的解决方案更快:

%%timeit
len([hasOnlyOneDuplicate(s) for s in test_words])
# 100 loops, best of 3: 10.9 ms per loop

答案 2 :(得分:1)

这是另一种方式:

from collections import Counter

def hasOnlyOneDuplicate(s):
     return len([c for c,v in Counter(s).items() if v > 1]) == 1

使用理解而不是filterlambda更具有pythonic。