On Sun, May 20, 2018 at 9:25 PM, Daniel Foerster <pydsig...@gmail.com>
wrote:

> The relevance of N exponent versus the discarded coefficients depends on
> how big N may be. With the likely sizes of N in a Pygame class, the
> difference between the algorithms seems probably negligible. A quick test
> with 20% deletion shows that your algorithm becomes more efficient around
> N=7000, but either can handle well over N=20000 in 10ms. Of course, a list
> comprehension can handle almost 100,000 in the same 10ms so the point is
> all rather moot in real-world code ;)
>

​These results were surprising to me, so I coded up a test (see attached!).

I measure the breakeven point at a similar level, 5500 elements. MrGumm's
version is functionally equivalent to mine, but seems to run much faster
than either of ours (mine and Daniel's)—almost as fast as the list
comprehension, which I confirm to be fastest. My guess is that my `while`
loop (instead of `for` over the elements explicitly) is confusing the
Python JIT into not optimizing somehow.

Also, this discussion on StackOverflow is relevant
<https://stackoverflow.com/questions/5745881/fast-way-to-remove-a-few-items-from-a-list-queue>
.

Ian​
import timeit


def listcomp_remove(my_list, delete_predicate):
    my_list[:] = [item for item in my_list if not delete_predicate(item)]
def daniel_remove(my_list, delete_predicate):
    index = 0
    while index < len(my_list):
        if delete_predicate(my_list[index]):
            del my_list[index]
        else:
            index += 1
def ian_remove(my_list, delete_predicate):
    i_read  = 0
    i_write = 0
    while i_read < len(my_list):
        item = my_list[i_read]
        i_read += 1
        if delete_predicate(item):
            pass
        else:
            my_list[i_write] = item
            i_write += 1
    while len(my_list) > i_write:
        my_list.pop()
def mrgumm_remove(my_list, delete_predicate):
    i_write = 0
    for item in my_list:
        if not delete_predicate(item):
            my_list[i_write] = item
            i_write += 1
    del my_list[i_write:len(my_list)]
def tyler_remove(my_list, delete_predicate):
    for val in reversed(my_list):
        if delete_predicate(val):
            my_list.remove(val)

def delete_third(item):
    return item%3 == 0
def delete_fifth(item):
    return item%5 == 0

def run_test_10(remove_alg, delete_predicate):
    my_list = list(range(0,10,1))
    print("Before: "+str(my_list))
    remove_alg(my_list,delete_predicate)
    print("After:  "+str(my_list))
run_test_10(listcomp_remove,delete_fifth)
run_test_10(daniel_remove,  delete_fifth)
run_test_10(ian_remove,     delete_fifth)
run_test_10(mrgumm_remove,  delete_fifth)
run_test_10(tyler_remove,   delete_fifth)

def run_test_n(remove_alg, delete_predicate, n):
    my_list = None
    def setup_list():
        nonlocal my_list
        my_list = list(range(0,n,1))
    def remove():
        nonlocal my_list
        remove_alg(my_list,delete_predicate)
    stats = timeit.repeat(stmt=remove,setup=setup_list, repeat=50,number=1)
    print(sum(stats)/len(stats))
run_test_n(listcomp_remove,delete_fifth, 5500)
run_test_n(daniel_remove,  delete_fifth, 5500)
run_test_n(ian_remove,     delete_fifth, 5500)
run_test_n(mrgumm_remove,  delete_fifth, 5500)
run_test_n(tyler_remove,   delete_fifth, 5500)

Reply via email to