Mesclando listas em python. Comparação de velocidade

Comparando métodos diferentes de mesclar duas listas classificadas



Suponha que temos duas listas (para simplificar os inteiros), cada uma delas classificada. Queremos combiná-los em uma lista, que também deve ser classificada. Essa tarefa provavelmente é familiar a todos; ela é usada, por exemplo, na classificação por mesclagem.





Existem muitas maneiras de implementação (especialmente em python). Vamos dar uma olhada em alguns deles e comparar o tempo decorrido para diferentes entradas.



A ideia principal do algoritmo é que ao colocar um rótulo no início de cada lista, iremos comparar os elementos marcados, pegar o menor e mover o rótulo de sua lista para o próximo número. Quando uma das listas termina, você precisa adicionar o resto da segunda ao final.



Os dados de entrada não mudam



Que haja duas listas list1e list2.



Vamos começar com o algoritmo mais simples: vamos marcar os rótulos para ie je pegar o menor list1[i], list2[j]e aumentar seu rótulo em um até que um dos rótulos ultrapasse o limite da lista.



, . , .



:



def simple_merge(list1, list2):
    i, j = 0, 0
    res = []
    while i < len(list1) and j < len(list2):
        if list1[i] < list2[j]:
            res.append(list1[i])
            i += 1
        else:
            res.append(list2[j])
            j += 1
    res += list1[i:]
    res += list2[j:] 
    #   list1[i:]  list2[j:]   ,     
    return res


, . . .



, . , , , , .



def iter_merge(list1, list2):
    result, it1, it2 = [], iter(list1), iter(list2)
    el1 = next(it1, None)
    el2 = next(it2, None)
    while el1 is not None or el2 is not None:
        if el1 is None or (el2 is not None and el2 < el1):
            result.append(el2)
            el2 = next(it2, None)
        else:
            result.append(el1)
            el1 = next(it1, None)
    return result


(result.append()) , . , , .



def gen_merge_inner(it1, it2):
    el1 = next(it1, None)
    el2 = next(it2, None)
    while el1 is not None or el2 is not None:
        if el1 is None or (el2 is not None and el2 < el1):
            yield el2
            el2 = next(it2, None)
        else:
            yield el1
            el1 = next(it1, None)

def gen_merge(list1, list2):
    return list(gen_merge_inner(iter(list1), iter(list2))) #    




python .



  • merge heapq. , , , : , , .



    :



    from heapq import merge
    
    def heapq_merge(list1, list2):
    return list(merge(list1, list2)) #   


  • Counter collections. Counter , , , , (, ).



    gen_merge_inner Counter(list1) Counter(list2):



    def counter_merge(list1, list2):
    return list(gen_merge_inner(Counter(list1).elements(), Counter(list2).elements()))


  • , , . .



    def sort_merge(list1, list2):
    return sorted(list1 + list2)






, ( ). . pop(0) , .



def pop_merge(list1, list2):
    result = []
    while list1 and list2:
        result.append((list1 if list1[0] < list2[0] else list2).pop(0))
    return result + list1 + list2


4 , . , , . , . , , .



def reverse_pop_merge(list1, list2):
    result = []
    while list1 and list2:
        result.append((list1 if list1[-1] > list2[-1] else list2).pop(-1))
    return (result + list1[-1::-1] + list2[-1::-1])[-1::-1]




.

, :



  • simple_merge
  • iter_merge
  • gen_merge
  • heapq_merge
  • counter_merge
  • sort_merge
  • pop_merge
  • reverse_pop_merge


timeit. .



: , , , , . .





, 1 dezcinco, 1 dez6.



pop reverse_pop:





pop_merge , .



pop_merge, :





reverse_pop_merge heapq_merge.



, , , .



,



[50x,50(x+1)), x , 1. 50.





pop_merge heapq_merge, .



, ,



x, dez4+100x.





( ) reverse_pop_merge , sort_merge, .



,



, cinco, 1.





, counter_merge reverse_pop_merge heapq_merge, .





sort_merge! , .



gen_merge, iter_merge.



, - 2-3 .



P.S.



, , jupyter notebook c gitlab.



, , .




All Articles