2016-05-22 2 views
0

Ich habe zwei verschiedene Abfragesätze, die ich zusammenführen muss und dann doppelte IDs entfernen. Es gibt über eine Million Aufzeichnungen.Der schnellste Weg in Python, doppelte IDs zu verschmelzen und zu entfernen

list_a = Wharehouse.orders.all().values_list('id', flat=True) 
list_b = Shops.orders.all().values_list('id', flat=True) 

Gibt es eine schnelle pythonische Art, dies zu tun?

Ich kann mir vorstellen, ein Listenverständnis zu verwenden und jeden Wert zu wiederholen. Aber, könnte das in numply besser/schneller oder vielleicht ein Set getan werden? Die Ausgabe muss nur eine Liste von IDs sein.

Ich benutze Python 3.4 und Django mit numpy 1.11.0 Pip installiert.

+3

Versuchen Sie, beide Ansätze zu verwenden und sie zu synchronisieren. –

Antwort

2

Angenommen, list_a und list_b sind Listen von Ganzzahlen, könnten Sie np.union1d(list_a, list_b) verwenden. Mit:

import numpy as np 
N = 10**6 
list_a = np.random.randint(2*10**6, size=N).tolist() 
list_b = np.random.randint(2*10**6, size=N).tolist() 

Hier ist ein Benchmark np.union1d was darauf hindeutet, schneller sein kann, wenn sie mit rund einer Million Elementen auf Listen angewendet:

In [32]: %timeit np.union1d(list_a, list_b) 
1 loop, best of 3: 296 ms per loop 

In [40]: %timeit set(list_a + list_b) 
1 loop, best of 3: 308 ms per loop 

In [31]: %timeit set(list_a).union(list_b) 
1 loop, best of 3: 338 ms per loop 

In [33]: %timeit list(set(list_a + list_b)) 
1 loop, best of 3: 382 ms per loop 

Hinweis, natürlich, dass np.union1d eine NumPy Array zurückgibt, während set und list Python-Objekte des gleichnamigen Typs zurückgeben, so ist der Benchmark zu einem gewissen Grad ein Apfel-zu-Orange-Vergleich.

1

Versuchen Sie, es auf set zu werfen, um die Duplikate zu entfernen. Sie können es dann zu einer Liste zurückgeben. Verwenden Sie zum Verketten der Listen den Operator +. Es wird genau diese (zumindest mit normalen Listen)

merged = list(set(list_a + list_b)) 
+0

Vielen Dank Vogon Jeltz, ein Set ist eine gute Idee, aber würde numpy schneller sein? – Prometheus

+1

Beachten Sie, dass 'ValuesListQuerySet' die Addition nicht unterstützt. Sie sollten sie zuerst in Listen oder eine andere Datenstruktur konvertieren. –

+0

@AshwiniChaudhary do'' flat = True'' nicht eine einfache Liste machen? – Prometheus

1

Eine Möglichkeit ist Sets.

Wir schaffen 2 Sätze set_a und set_b zu verwenden. set_a enthält alle IDs von Wharehouse Objekte. set_b enthält alle Shops IDs. Um nun alle eindeutigen IDs zu kombinieren, verwenden wir union Operation auf Sets. final_set enthält alle gewünschten eindeutigen IDs.

set_a = set(Wharehouse.orders.all().values_list('id', flat=True)) 
set_b = set(Shops.orders.all().values_list('id', flat=True)) 

final_set = set_a.union(set_b) # contains all unique ids combined 
0
shops_query=Shops.orders.all().values_list('id', flat=True) 
result = Wharehouse.orders.all().exclude(id__in=shops_query).values_list('id', flat=True) 

die DB die Arbeit machen lassen.

+1

Aber Sie brauchen noch eine Operation, um die tatsächliche Vereinigung zu erhalten, d. H. "Ergebnis" ist hier nicht das tatsächliche Ergebnis. Je nachdem, ob die Datenbank ein anderes Abfrage-Set in '__in' verwendet, kann es sich als langsam herausstellen. Sie sollten die Ergebnisse von 'shops_query' zuerst in eine' list() 'konvertieren, bevor Sie sie an die nächste Abfrage übergeben, um sie auf eine einzige Abfrage für die' shop_query' IDs zu reduzieren. –

Verwandte Themen