2016-08-09 192 views
0

Ich habe zwei Listen, beide ziemlich lang. Liste A enthält eine Liste von ganzen Zahlen, von denen einige in Liste B wiederholt I, die Elemente erscheinen in beide unter Verwendung finden können:Übereinstimmende Elemente zwischen Listen in Python - Position beibehalten

idx = set(list_A).intersection(list_B) 

Dies gibt eine Menge aller Elemente erscheinen in beiden Liste A und Liste B.

Allerdings würde ich gerne einen Weg finden, die Übereinstimmungen zwischen den beiden Listen zu finden und auch Informationen über die Positionen der Elemente in beiden Listen zu behalten. Eine solche könnte eine Funktion wie folgt aussehen:

def match_lists(list_A,list_B): 
. 
. 
. 
return match_A,match_B 

wo match_A die Positionen der Elemente in list_A enthalten würde, die eine Übereinstimmung irgendwo in list_B und umgekehrt für match_B hatte. Ich kann sehen, wie man solche Listen mit einer For-Schleife erstellt, aber das fühlt sich an, als wäre es für lange Listen unerschwinglich langsam.

Für Duplikate: list_B enthält keine Duplikate, wenn es ein Duplikat in list_A gibt, geben Sie alle übereinstimmenden Positionen als Liste zurück, so dass match_A eine Liste von Listen wäre.

+1

Wie wollen Sie Duplikate in 'list_A' oder' list_B' behandeln? –

Antwort

-1

Try this:

def match_lists(list_A, list_B): 
    match_A = {} 
    match_B = {} 
    for elem in list_A: 
     if elem in list_B: 
      match_A[elem] = list_A.index(elem) 
      match_B[elem] = list_B.index(elem) 

    return match_A, match_B 
+1

Diese Lösung würde funktionieren, aber es ist sehr langsam. Für jedes Element der Liste A durchsuchen Sie die gesamte Liste B, die O (n^2) ergibt. Auch 'index' gibt das erste Vorkommen zurück, so dass es fehlschlägt, wenn es Wiederholungen gibt. – warownia1

1

Wie wäre es damit:

def match_lists(list_A, list_B): 
    idx = set(list_A).intersection(list_B) 
    A_indexes = [] 
    for i, element in enumerate(list_A): 
     if element in idx: 
      A_indexes.append(i) 
    B_indexes = [] 
    for i, element in enumerate(list_B): 
     if element in idx: 
      B_indexes.append(i) 
    return A_indexes, B_indexes 
+0

Sie haben den Tippfehler (zweites 'A_indexes' sollte' B_indexes' sein). – ShadowRanger

3

, die den Job tun sollte :)

def match_list(list_A, list_B): 
    intersect = set(list_A).intersection(list_B) 
    interPosA = [[i for i, x in enumerate(list_A) if x == dup] for dup in intersect] 
    interPosB = [i for i, x in enumerate(list_B) if x in intersect] 
    return interPosA, interPosB 

(Dank Maschine Sehnsucht nach doppelten edit)

+0

Ich habe die gleiche Lösung nur vor ein paar Sekunden, aber Ihr verwendet Verständnis und ist schneller: p – warownia1

+0

Ihre Lösung arbeitete auch und ist vielleicht verständlicher für jemanden, der nicht in Liste Verständnis ist :) (Aber es gibt nur A_indexes und keine zurück?) – Sygmei

+1

Um seine Anforderung an Duplikate anzupassen, benötigen Sie etwas wie '[[i für i, x in enumerate (list_A) wenn x == dup] für dup in intersect) ' –

2

Verwenden Sie dict s oder defaultdict s die eindeutigen Werte zu speichern, wie Schlüssel, die bei den Indizes erscheinen sie abzubilden, dann verbinden die dicts:

from collections import defaultdict 

def make_offset_dict(it): 
    ret = defaultdict(list) # Or set, the values are unique indices either way 
    for i, x in enumerate(it): 
     ret[x].append(i) 

dictA = make_offset_dict(A) 
dictB = make_offset_dict(B) 
for k in dictA.viewkeys() & dictB.viewkeys(): # Plain .keys() on Py3 
    print(k, dictA[k], dictB[k]) 

Diese Iterierten A und B genau einmal jeder so funktioniert es, auch wenn sie eine sind -time Verwendung von Iteratoren, z von einem dateiähnlichen Objekt, und es funktioniert effizient, speichert nicht mehr Daten als nötig und bleibt bei billigen Hash-basierten Operationen statt wiederholter Iteration. Diese

ist nicht die Lösung für Ihr Problem, aber es bewahrt alle erforderlichen Informationen, um Ihr Problem zu lösen und dann einige (zB es ist billig, um herauszufinden, wo die Spiele für einen bestimmten Wert befinden sich entweder in A oder B); Sie können es einfach an Ihren Anwendungsfall oder kompliziertere anpassen.

0

Dies ist nur durch jede Liste wird einmal (erfordert nur ein dict) und arbeitet auch mit Dubletten in list_B

def match_lists(list_A,list_B): 
    da=dict((e,i) for i,e in enumerate(list_A)) 
    for bi,e in enumerate(list_B): 
     try: 
      ai=da[e]   
      yield (e,ai,bi) # element e is in position ai in list_A and bi in list_B 
     except KeyError: 
      pass 
+1

Angenommen, Python 2.7 oder höher, könnten Sie einfach verwenden ein 'dict'-Verständnis für die erste Zeile der Funktion; schneller und besser lesbar. Das heißt, es ist problematisch, weil es nur einen einzigen Index für einen gegebenen Wert verwaltet, nicht alle Indizes (deshalb musste ich "defaultdict (list)" in meiner Antwort verwenden und Verständnis vermeiden). – ShadowRanger