Combinar dos listas y eliminar duplicados, sin eliminar duplicados en la lista original

115

Tengo dos listas que necesito combinar donde la segunda lista tiene cualquier duplicado de la primera lista ignorado. .. Un poco difícil de explicar, así que déjame mostrarte un ejemplo de cómo se ve el código y lo que quiero como resultado.

first_list = [1, 2, 2, 5]

second_list = [2, 5, 7, 9]

# The result of combining the two lists should result in this list:
resulting_list = [1, 2, 2, 5, 7, 9]

Notará que el resultado tiene la primera lista, incluidos sus dos valores "2", pero el hecho de que second_list también tiene un valor adicional de 2 y 5 no se agrega a la primera lista.

Normalmente, para algo como esto, usaría conjuntos, pero un conjunto en first_list eliminaría los valores duplicados que ya tiene. Así que simplemente me pregunto cuál es la mejor / más rápida forma de lograr esta combinación deseada.

Gracias.

Lee Olayvar
fuente
3
¿Qué pasa si hay tres 2 en second_list?
balpha
@balpha: Sí, todavía no he decidido por completo cómo quiero manejar eso. Es algo en lo que había pensado, pero lo dejé de lado dada mi indecisión al respecto :)
Lee Olayvar

Respuestas:

168

Debe agregar a la primera lista los elementos de la segunda lista que no están en la primera; los conjuntos son la forma más fácil de determinar qué elementos son, así:

first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

in_first = set(first_list)
in_second = set(second_list)

in_second_but_not_in_first = in_second - in_first

result = first_list + list(in_second_but_not_in_first)
print(result)  # Prints [1, 2, 2, 5, 9, 7]

O si lo prefiere de una sola línea 8-)

print(first_list + list(set(second_list) - set(first_list)))
RichieHindle
fuente
2
O esto si lo necesita ordenado: imprima first_list + sorted (set (second_list) - set (first_list))
hughdbrown
2
Lista (conjunto (primera_lista) | conjunto (segunda_lista)) # | se establece intersección ver stackoverflow.com/questions/4674013/…
staticd
1
@staticd: Sí, pero eso da una respuesta incorrecta. Solo hay uno 2en su resultado, cuando debería haber dos de ellos.
RichieHindle
Ups. Tienes razón. Perdí por completo que se permitieran duplicados a la primera lista . : P
staticd
66
resulting_list = list(first_list)
resulting_list.extend(x for x in second_list if x not in resulting_list)
Ned Batchelder
fuente
7
¡Finalmente una respuesta que no implica lanzar conjuntos! Prestigio.
SuperFamousGuy
4
esto es, de hecho, O (n * m) pero puede ser útil cuando tienes una lista de cosas que no se pueden mezclar y el rendimiento no es una preocupación
alcuadrado
1
¿Qué no quiero que se duplique ni del primero ni del segundo?
Dejell
Esta técnica conserva el orden de los atributos en la lista, lo que no es el caso de set. 👍
Subhash Bhushan
29

Puedes usar conjuntos:

first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

resultList= list(set(first_list) | set(second_list))

print(resultList)
# Results in : resultList = [1,2,5,7,9]
Kathiravan Umaidurai
fuente
Sí, gracias lo tengo. Esto funcionará bien. resultList = first_list + list (set (second_list) -set (first_list))
Kathiravan Umaidurai
9

Puede reducir esto a una sola línea de código si usa numpy:

a = [1,2,3,4,5,6,7]
b = [2,4,7,8,9,10,11,12]

sorted(np.unique(a+b))

>>> [1,2,3,4,5,6,7,8,9,10,11,12]
mosegui
fuente
7
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

print( set( first_list + second_list ) )
Paul Roub
fuente
5
resulting_list = first_list + [i for i in second_list if i not in first_list]
Daniel Roseman
fuente
1
setify first_list y estará "listo"
u0b34a0f6ae
La lista resultante no se ordenará.
Avakar
1
¿Qué sucede si tampoco quiero que ninguna lista tenga duplicados? de esta manera, si una lista tiene duplicados, regresarán
Dejell
5

Lo más simple para mí es:

first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

merged_list = list(set(first_list+second_list))
print(merged_list)

#prints [1, 2, 5, 7, 9]
Rafiq
fuente
1
Esa es una gran solución, pero tenga en cuenta que no funcionará si intentamos hacer un conjunto de diccionarios, por ejemplo, (aumentará TypeError: unhashable type: 'dict')
lakesare
2

También puede combinar las respuestas de RichieHindle y Ned Batchelder para un algoritmo O (m + n) de caso promedio que preserva el orden:

first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

fs = set(first_list)
resulting_list = first_list + [x for x in second_list if x not in fs]

assert(resulting_list == [1, 2, 2, 5, 7, 9])

Tenga en cuenta que x in stiene una complejidad en el peor de los casos de O (m) , por lo que la complejidad del peor de los casos de este código sigue siendo O (m * n) .

z0r
fuente
0

Esto puede ayudar

def union(a,b):
    for e in b:
        if e not in a:
            a.append(e)

La función de unión fusiona la segunda lista con la primera, sin duplicar un elemento de a, si ya está en a. Similar a establecer un operador de unión. Esta función no cambia b. Si a = [1,2,3] b = [2,3,4]. Después de la unión (a, b) hace a = [1,2,3,4] yb = [2,3,4]

VeloEclipse
fuente
0

Basado en la receta :

lista_resultantes = lista (conjunto (). unión (primera_lista, segunda_lista))

solo
fuente
-2
    first_list = [1, 2, 2, 5]
    second_list = [2, 5, 7, 9]

    newList=[]
    for i in first_list:
        newList.append(i)
    for z in second_list:
        if z not in newList:
            newList.append(z)
    newList.sort()
    print newList

[1, 2, 2, 5, 7, 9]

usuario4846254
fuente