Python 高效地查找字符串中的重复字符

Python 高效地查找字符串中的重复字符,python,string,performance,Python,String,Performance,我知道这段代码的效率不是最优的(特别是在输入量巨大的情况下),而且我知道有一种方法可以改变此算法来处理其他数据类型,而不仅仅是字符串中的重复(显然,要搜索的字符太多了) 有什么办法可以提高这里的效率吗 我尝试使用字典,但函数始终返回“none”,所以我尝试了一个列表,结果很好 提前感谢所有能帮助我的人 def find_repeater(string): my_list = [] my_list.append(string[0]) for i in range (1,

我知道这段代码的效率不是最优的(特别是在输入量巨大的情况下),而且我知道有一种方法可以改变此算法来处理其他数据类型,而不仅仅是字符串中的重复(显然,要搜索的字符太多了)

有什么办法可以提高这里的效率吗

我尝试使用字典,但函数始终返回“none”,所以我尝试了一个列表,结果很好

提前感谢所有能帮助我的人

def find_repeater(string):
    my_list = []
    my_list.append(string[0])

    for i in range (1, len(string)):

        if string[i] in my_list:
            print 'repetition found'
            return (string[i])

        else:
            my_list.append(string[i])

print find_repeater('abca')  
现在有了字典……(它一直在控制台上打印“无”)


给你,用字典:

def find_repeater(string):
    my_list = {}
    my_list[string[0]] = 1
    for i in range (1, len(string)):
        if string[i] in my_list.keys():
            print 'repetition found'
            return (string[i])
        else:
            my_list[string[i]] = 1
print find_repeater('abca')  
但就我个人而言,我会在这里使用一个集合:

def find_repeater(string):
    my_list = set()
    my_list.add(string[0])
    for i in range (1, len(string)):
        if string[i] in my_list:
            print 'repetition found'
            return (string[i])
        else:
            my_list.add(string[i])
print find_repeater('abca')  

您可以使用
集合
查找重复字符:

import collections

freq = collections.Counter("abcda")
for k in freq:
    if freq[k] > 1:
        print k # prints "a"
        break
letters = list("abcda")
no_rep = set(letters)
print len(letters) > len(no_rep) # prints 'True' when there are repeating characters
如果只想查找是否存在重复(而不查找重复的字符):


由于这是一个性能问题,让我们进行一些计时:

def test_set(xs):
    seen = set()  # O(1) lookups
    for x in xs:
        if x not in seen:
            seen.add(x)
        else:
            return x

import collections

def test_counter(xs):
    freq = collections.Counter(xs)
    for k in freq:
        if freq[k] > 1:
            return k

def test_dict(xs):
    d = {}
    for x in xs:
        if x in d:
            return x
        d[x] = 1

def test_sort(xs):
    ys = sorted(xs)

    for n in range(1, len(xs)):
        if ys[n] == ys[n-1]:
            return ys[n]

##

import sys, timeit
print (sys.version + "\n")
xs = list(range(10000)) + [999]
fns = [p for name, p in globals().items() if name.startswith('test')]
for fn in fns:
    assert fn(xs) == 999
    print ('%50s %.5f' % (fn, timeit.timeit(lambda: fn(xs), number=100)))
我测试的是一个整数列表,而不是一个字符串(因为一个字符串的循环数不能超过256个)。我的机器上的结果如下所示:

3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

                <function test_set at 0x1020f7380> 0.19265
               <function test_dict at 0x1020f7490> 0.12725
               <function test_sort at 0x1020f7518> 0.04683
            <function test_counter at 0x1020f7408> 0.92485
3.2.3(v3.2.3:3D0686D90F552012年4月10日11:25:50)
[GCC 4.2.1(Apple Inc.build 5666)(dot 3)]
0.19265
0.12725
0.04683
0.92485
因此,排序方法似乎是赢家。我想这是因为它不会浪费时间创建散列和分配dict/set结构。另外,如果您不关心源列表的更改,那么可以执行
xs.sort()
而不是
ys=sorted(xs)
,这样就不会占用内存

另一方面,如果在输入开始时更可能出现重复项(如
xs='abcdef'*10000
),则
set
方法的性能最好,因为它与
sort
Counter
不同,在发现重复项后立即返回,并且不需要预处理整个列表。如果需要第一个重复元素,而不仅仅是其中一个,那么还应该使用
set

计数器是一个很好的工具,但它不是为性能而设计的,所以如果你真的要处理“巨大的输入”,那么就使用集合(如果它们适合内存),如果它们不适合,就合并排序。

这应该行得通

def return_dupe(string):
    d = {}
    [d.update({k:2}) if k in d else d.update({k:1}) for k in string]
    return [key for key in d if d[key] > 1]

另一种方法可以简单到:

def repeting_count(text):

    working_text = str(text.lower())

    dup = []

    for char in working_text:
        if working_text.count(char) > 1:
            dup.append(char)

        else:
            pass

    for num in dup:
        while dup.count(num) > 1:
            dup.remove(num)

python3中的此函数的时间复杂度为O(n),它将打印多次出现的字符。

使用字典是一种方法。显示您尝试的内容,我们将帮助您修复。如果有多个重复的字母怎么办?@PadraicCunningham:看起来OP想要返回首先重复的字母。您可以先对输入进行排序吗?如果您有工作代码,但效率不够高,那么代码检查可能是一个不错的过程(目前还不是这样)。但是无论如何,考虑使用一个合适的标题来描述你想要帮助的问题,而不是仅仅求助于呼喊。虽然你只想在正确的方向上稍微戳一下,而不是整个解决方案,但还是值得称赞的。OP要求一本字典。应该给出两个答案,就像我做的那样,为什么要使用range而不是在字符串上迭代呢?不要认为你需要将集合转换成列表或将字母列成列表,
letters=(“abcda”)
len(letters)>len(set(letters))
@padraickenningham对!(thx-修复),我忘了删除它(在发布它之前正在玩其他选项)。不用担心,+1是,也要发布一个反答案,只是太懒了:)在这个例子中排序不会是一个优势,因为您已经有一个列表,除了一个值之外,其他所有值都被排序了?设置xs后放置random.shuffle(xs)会使sort成为最差的执行者,或者与counter并列。
def return_dupe(string):
    d = {}
    [d.update({k:2}) if k in d else d.update({k:1}) for k in string]
    return [key for key in d if d[key] > 1]
def repeting_count(text):

    working_text = str(text.lower())

    dup = []

    for char in working_text:
        if working_text.count(char) > 1:
            dup.append(char)

        else:
            pass

    for num in dup:
        while dup.count(num) > 1:
            dup.remove(num)
def rec_char(s):
    buf={}
    for c in s:
        try:
            print(buf[c],end=", ")
        except:
            buf[c]=c


rec_char("ABCAB")