How to find the first index of any of a set of characters in a string

后端 未结 4 1461
梦毁少年i
梦毁少年i 2020-12-20 11:44

I\'d like to find the index of the first occurrence of any “special” character in a string, like so:

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


        
4条回答
  •  无人及你
    2020-12-20 12:27

    You can use enumerate and next with a generator expression, getting the first match or returning None if no character appears in s:

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

    You can pass any value you want to next as a default return value if there is no match.

    If you want to use a function and raise a 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
    

    For smaller inputs using a set won't make much if any difference but for large strings it will be a more efficient.

    Some timings:

    In the string, last character of character set:

    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
    

    Not in the string, larger character set:

    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 string an very first character of character set:

    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
    

提交回复
热议问题