如何查找字符串中任何字符集的第一个索引

发布于 2021-01-29 14:58:55

我想找到字符串中任何“特殊”字符首次出现的索引,如下所示:

>>> "Hello world!".index([' ', '!'])
5

…除非那是无效的Python语法。当然,我可以编写一个模拟此行为的函数:

def first_index(s, characters):
    i = []
    for c in characters:
        try:
            i.append(s.index(c))
        except ValueError:
            pass
    if not i:
        raise ValueError
    return min(i)

我也可以使用正则表达式,但两种解决方案似乎都有些过分。在Python中有什么“明智”的方法吗?

关注者
0
被浏览
94
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您可以将enumeratenext生成器表达式一起使用,获取第一个匹配项,或者如果s中没有字符,则返回None:

    s = "Hello world!"
    
    st = {"!"," "}
    ind = next((i for i, ch  in enumerate(s) if ch in st),None)
    print(ind)
    

    如果没有匹配项,则可以将您想要的下一个值作为默认返回值传递。

    如果要使用函数并引发ValueError:

    def first_index(s, characters):
        st = set(characters)
        ind = next((i for i, ch in enumerate(s) if ch in st), None)
        if ind is not None:
            return ind
        raise ValueError
    

    对于较小的输入,使用集合不会有什么区别,但是对于较大的字符串,则效率更高。

    一些时间:

    在字符串中,字符集的最后一个字符:

    In [40]: s = "Hello world!" * 100    
    In [41]: string = s    
    In [42]: %%timeit
    st = {"x","y","!"}
    next((i for i, ch in enumerate(s) if ch in st), None)
       ....: 
    1000000 loops, best of 3: 1.71 µs per loop    
    In [43]: %%timeit
    specials = ['x', 'y', '!']
    min(map(lambda x: (string.index(x) if (x in string) else len(string)), specials))
       ....: 
    100000 loops, best of 3: 2.64 µs per loop
    

    不在字符串中,较大的字符集:

    In [44]: %%timeit
    st = {"u","v","w","x","y","z"}
    next((i for i, ch in enumerate(s) if ch in st), None)
       ....: 
    1000000 loops, best of 3: 1.49 µs per loop
    
    In [45]: %%timeit
    specials = ["u","v","w","x","y","z"]
    min(map(lambda x: (string.index(x) if (x in string) else len(string)), specials))
       ....: 
    100000 loops, best of 3: 5.48 µs per loop
    

    在字符串中,字符集的第一个字符:

    In [47]: %%timeit
    specials = ['H', 'y', '!']
    min(map(lambda x: (string.index(x) if (x in string) else len(string)), specials))
       ....: 
    100000 loops, best of 3: 2.02 µs per loop
    
    In [48]: %%timeit
    st = {"H","y","!"}
    next((i for i, ch in enumerate(s) if ch in st), None)
       ....: 
    1000000 loops, best of 3: 903 ns per loop
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看