finding and replacing elements in a list

前端 未结 16 2440
南方客
南方客 2020-11-22 05:41

I have to search through a list and replace all occurrences of one element with another. So far my attempts in code are getting me nowhere, what is the best way to do this?<

16条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-22 06:07

    My usecase was replacing None with some default value.

    I've timed approaches to this problem that were presented here, including the one by @kxr - using str.count.

    Test code in ipython with Python 3.8.1:

    def rep1(lst, replacer = 0):
        ''' List comprehension, new list '''
    
        return [item if item is not None else replacer for item in lst]
    
    
    def rep2(lst, replacer = 0):
        ''' List comprehension, in-place '''    
        lst[:] =  [item if item is not None else replacer for item in lst]
    
        return lst
    
    
    def rep3(lst, replacer = 0):
        ''' enumerate() with comparison - in-place '''
        for idx, item in enumerate(lst):
            if item is None:
                lst[idx] = replacer
    
        return lst
    
    
    def rep4(lst, replacer = 0):
        ''' Using str.index + Exception, in-place '''
    
        idx = -1
        # none_amount = lst.count(None)
        while True:
            try:
                idx = lst.index(None, idx+1)
            except ValueError:
                break
            else:
                lst[idx] = replacer
    
        return lst
    
    
    def rep5(lst, replacer = 0):
        ''' Using str.index + str.count, in-place '''
    
        idx = -1
        for _ in range(lst.count(None)):
            idx = lst.index(None, idx+1)
            lst[idx] = replacer
    
        return lst
    
    
    def rep6(lst, replacer = 0):
        ''' Using map, return map iterator '''
    
        return map(lambda item: item if item is not None else replacer, lst)
    
    
    def rep7(lst, replacer = 0):
        ''' Using map, return new list '''
    
        return list(map(lambda item: item if item is not None else replacer, lst))
    
    
    lst = [5]*10**6
    # lst = [None]*10**6
    
    %timeit rep1(lst)    
    %timeit rep2(lst)    
    %timeit rep3(lst)    
    %timeit rep4(lst)    
    %timeit rep5(lst)    
    %timeit rep6(lst)    
    %timeit rep7(lst)    
    

    I get:

    26.3 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    29.3 ms ± 206 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    33.8 ms ± 191 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    11.9 ms ± 37.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    11.9 ms ± 60.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    260 ns ± 1.84 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    56.5 ms ± 204 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

    Using the internal str.index is in fact faster than any manual comparison.

    I didn't know if the exception in test 4 would be more laborious than using str.count, the difference seems negligible.

    Note that map() (test 6) returns an iterator and not an actual list, thus test 7.

提交回复
热议问题