Python 字符串中第二个重复字符的索引

Python 字符串中第二个重复字符的索引,python,string,Python,String,我正在试用python中的刽子手代码。为了匹配一个单词的字符,iam使用索引函数获取字符的位置。 例如:word=‘计算机’ user_input = raw_input('Enter a character :') # say 'T; is given here if user_input in word: print "\nThe Character %c is present in the word \n" %user_input

我正在试用python中的刽子手代码。为了匹配一个单词的字符,iam使用索引函数获取字符的位置。 例如:word=‘计算机’

user_input = raw_input('Enter a character :') # say 'T; is given here

if user_input in word:
                print "\nThe Character %c is present in the word \n" %user_input 
                word_dict[word.index(user_input)] = user_input

#so the output will looks like

{0: '_', 1: '_', 2: '_', 3: '_', 4: '_', 5: 'T', 6: '_', 7: '_'} 
现在,我的问题来了,当它与重复字符

# Another example 
>>> 'CARTOON'.index('O')
4
对于第二个“O”,如何获取其索引。因为我使用了这个“索引”逻辑,所以我希望继续这样做。

根据签名,签名如下

str.index(sub[, start[, end]])
data = 'CARTOON'
print data.index('O', data.index('O') + 1)
def get_second_index(input_string, sub_string):
    return input_string.index(sub_string, input_string.index(sub_string) + 1)

print get_second_index("CARTOON", "O")
第二个参数是要从中搜索的起始索引。因此,您可以将第一项的索引+1传递给下一个索引

i = 'CARTOON'.index('O')
print 'CARTOON'.index('O', i + 1)
输出

5
上面的代码可以这样编写

str.index(sub[, start[, end]])
data = 'CARTOON'
print data.index('O', data.index('O') + 1)
def get_second_index(input_string, sub_string):
    return input_string.index(sub_string, input_string.index(sub_string) + 1)

print get_second_index("CARTOON", "O")
您甚至可以将其作为一个实用函数,如下所示

str.index(sub[, start[, end]])
data = 'CARTOON'
print data.index('O', data.index('O') + 1)
def get_second_index(input_string, sub_string):
    return input_string.index(sub_string, input_string.index(sub_string) + 1)

print get_second_index("CARTOON", "O")
注意:如果至少两次找不到字符串,这将抛出
ValueError

更广义地说

def get_index(input_string, sub_string, ordinal):
    current = -1
    for i in range(ordinal):
        current = input_string.index(sub_string, current + 1)
    else:
        raise ValueError("ordinal {} - is invalid".format(ordinal))
    return current

print get_index("AAABBBCCCC", "C", 4)

你问过如何找到第二个事件,得到了一个很好的答案,适用于任何特定事件。然而,你会意识到你真正想要的是一次发生所有事情。这里有一个方法:

def find_characters(word, character):
    found = []
    last_index = -1
    while True:
        try:
            last_index = word.index(character, last_index+1)
        except ValueError:
            break
        else:
            found.append(last_index)
    return found

您可以使用字符串的计数方法来查找用户输入在字符串中出现的次数。然后,对word中每次出现的用户输入使用str.index(sub,start)方法,每次递增start 1,这样就不会每次都得到相同的索引

if user_input in word:
    count=word.count(user_input)
    a=word.index(user_input)
    word_dict[word.index(a)]=user_input
    for i in range(count-1):
        a=word.index(user_input,a+1)
        word_dict[word.index(a)]=user_input

如果您使用
filter
,这应该是一个单行程序,因为如果您使用
index
,您将被迫进行迭代或使用递归。在这种情况下,两种方法都完全没有必要。您只需过滤掉与您相关的值

使用
过滤器
很容易。以下是一个示例实现:

def f1(w,c) : return zip(* filter(lambda (x,y): x == c, zip(w, range(len(w)))  ))[1]
f1('cartoon', 'o') # --> (4, 5)
您始终可以添加错误检查,如下所示:

def f1(w,c) :
    if c not in w: return ()
    else:          return zip(* filter(lambda (x,y): x == c, zip(w, range(len(w)))  ))[1]
如果在字符串中找不到该字符,则只会得到一个空元组。否则,您将获得匹配的所有元素。如果你想要一些通用的东西,指望一个角色只有一个或两个实例是不正确的。比如说,

In [18]: f1('supercalifragilisticexpialidocious', 'i')
Out[18]: (8, 13, 15, 18, 23, 26, 30)

希望这有助于…

一种可能更具python风格的方法是使用生成器,从而避免中间数组“found”:

def find_indices_of(char, in_string):
    index = -1
    while True:
        index = in_string.find(char, index + 1)
        if index == -1:
            break
        yield index

for i in find_indices_of('x', 'axccxx'):
    print i

1
4
5
另一种方法是内置枚举

def find_indices_of_via_enumerate(char, in_string):
    return (index for index, c in enumerate(in_string) if char == c)
这也使用了发电机

然后,我对性能差异感到好奇。我已经开始使用python一年了,所以我才刚刚开始感觉到真正的知识渊博。下面是一个快速测试,包含各种类型的数据:

test_cases = [
    ('x', ''),
    ('x', 'axxxxxxxxxxxx'),
    ('x', 'abcdefghijklmnopqrstuvw_yz'),
    ('x', 'abcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvwxyz'),
]

for test_case in test_cases:
    print "('{}', '{}')".format(*test_case)

    print "string.find:", timeit.repeat(
        "[i for i in find_indices_of('{}', '{}')]".format(*test_case),
        "from __main__ import find_indices_of",
    )
    print "enumerate  :", timeit.repeat(
        "[i for i in find_indices_of_via_enumerate('{}', '{}')]".format(*test_case),
        "from __main__ import find_indices_of_via_enumerate",
    )
    print
在我的机器上,这会导致以下计时:

('x', '')
string.find: [0.6248660087585449, 0.6235580444335938, 0.6264920234680176]
enumerate  : [0.9158611297607422, 0.9153609275817871, 0.9118690490722656]

('x', 'axxxxxxxxxxxx')
string.find: [6.01502799987793, 6.077538013458252, 5.997750997543335]
enumerate  : [3.595151901245117, 3.5859270095825195, 3.597352981567383]

('x', 'abcdefghijklmnopqrstuvw_yz')
string.find: [0.6462750434875488, 0.6512351036071777, 0.6495819091796875]
enumerate  : [2.6581480503082275, 2.6216518878936768, 2.6187551021575928]

('x', 'abcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvwxyz')
string.find: [1.2539417743682861, 1.2511990070343018, 1.2702908515930176]
enumerate  : [7.837890863418579, 7.791800022125244, 7.9181809425354]

enumerate()方法更具表现力和Python风格。性能差异是否重要取决于实际用例

这里是另一个例子

a="samesame"
po=-1 # for this, po+1 is start from 0

for c in a:
    if c=='s':  # For example, I chose "S" what I want to find
        po = a.index(c,po+1) # if you find first element 'C' then search again in next postion
        print(po)

我正在寻找一种基于刽子手游戏的通用解决方案卡通片只是一个例子。希望你得到我想要的@rajeshes请检查我现在包含的通用版本。您的通用版本总是导致ValueError,因为循环总是完成,因此执行else块。可以简单地删除else块。将range(len(w))替换为enumerate:
def f1(w,c):返回zip(*filter(lambda(x,y):y==c,enumerate(w))[0]
是的,这更像Pythonic,当然更易于阅读!我早该想到的。谢谢你指出这一点。