Seite 1 von 1

Überprüfung wie viele items in set

Verfasst: Dienstag 8. September 2015, 07:13
von schneitzmaster
Hallo Leute,

ich habe ein "Haupt"-liste mit integern und eine verschachtelte liste ebenfals mit integern. Nun möchte ich die elemente der verschachtelten Liste heraus ziehen, die genau 3 elemente mit der "Haupt"-liste gemeinsam haben. Je nach dem welche position die gemeinsamen Elemente der haben soll noch in 4 Fälle unterschieden werden.
Momentan läuft das über eine for-schleife in kombination mit einer list-comprehension über:

Code: Alles auswählen

# INPUT
hauptliste= [1,2,3,4,5,6,7,8,9]
sub_liste = [[1,2,10,4],
             [5,20,10,9],
             [8,30,5,7]]
# INPUT-ENDE
hauptliste = set(hauptliste)
rslt = []
for i,sub_liste_i in enumerate(sub_liste):
    tmp = [item in hauptliste for item in sub_liste_i]
    if sum(tmp)==3:
        if   tmp[0] and tmp[1] and tmp[2]: # CASE 1
            rslt.append([i,1])
        elif tmp[0] and tmp[1] and tmp[3]: # CASE 2
            rslt.append([i,2])
        elif tmp[1] and tmp[2] and tmp[3]: # CASE 3
            rslt.append([i,3])
        else:
            rslt.append([i,4]) # CASE 4

print rslt
Geht das noch schneller und eleganter, da in der Realität die "Haupt"liste sehr groß ist. Gibt es da vllt. etwas in numpy? Ich bin leider noch nicht fündig geworden.
Grüße

Re: Überprüfung wie viele items in set

Verfasst: Dienstag 8. September 2015, 07:46
von MagBen
Mit Numpy geht das auch mit Millionen von Werten performant.

Code: Alles auswählen

import numpy as np

hauptliste= np.array([1,2,3,4,5,6,7,8,9])
sub_liste = np.array([[1,2,10,4],
                      [5,20,10,9],
                      [8,30,5,7]])

position = np.searchsorted(hauptliste, sub_liste)
position[position==hauptliste.size] = 0
uebereinstimmung = (hauptliste[position]==sub_liste)
anzahl = np.array([np.count_nonzero(zeile) for zeile in uebereinstimmung])
ergebnis = np.arange(anzahl.size)[anzahl==3] 
print ergebnis # [0 2]
print sub_liste[uebereinstimmung[ergebnis]].reshape(-1,3)
# [[ 1  2  4]
#  [ 5 10  9]] 
Damit der Code funktioniert, müssen die Werte der Hauptliste sortiert sein und alle Zeilen der sub_liste müssen die gleiche Anzahl an Elementen haben. Wegen dem Trick in Zeile 9 muss die Hauptliste mindestens 2 Elemente enthalten. Nur Zeile 11 enthält eine Schleife in Python, alle anderen Schleifen laufen extrem schnell innerhalb von Numpy. Die runden Klammern in Zeile 10 sind nicht notwendig, macht die Sache aber klarer.

Re: Überprüfung wie viele items in set

Verfasst: Dienstag 8. September 2015, 08:35
von schneitzmaster
super vielen dank!
genau nach so etwas habe ich gesucht.

Re: Überprüfung wie viele items in set

Verfasst: Dienstag 8. September 2015, 08:37
von BlackJack
@schneitzmaster: `set` kommt zwar im Betreff vor und sogar in einer Zeile im Quelltext, dort führt es aber zu einem `NameError` weil `liste` nicht definiert ist. Und wenn es in der Zeile definiert würde: Der Name wird sonst nirgends verwendet.

Die Namen sind insgesamt nicht so toll. `rslt`? Sind auf Deiner Tastatur keine Vokale, oder muss man extra bezahlen wenn man die benutzt? `sub_liste` enthält Listen (Mehrzahl), sollte also `sub_listen` heissen. Und schön bräuche man für eine dieser Unterlisten kein komisches `_i` mehr an den Namen `sub_liste` hängen.

Alternative:

Code: Alles auswählen

def function(main_list, sub_lists):
    main_list = set(main_list)
    result = list()
    for i, sub_list in enumerate(sub_lists):
        positions = [j for j, x in enumerate(sub_list) if x in main_list]
        # 
        # Alternative wenn `sub_list` deutlich länger als im Beispiel sein
        # kann, dann könnte man etwas gewinnen in dem man die Suche nach
        # den Positionen auf das Minimum begrenzt das nötig ist um die
        # nachfolgende Entscheidung zu treffen:
        # 
        # positions = list(
        #     islice((j for j, x in enumerate(sub_list) if x in main_list), 4)
        # )
        # 
        if len(positions) == 3:
            for k, case in enumerate([[0, 1, 2], [0, 1, 3], [1, 2, 3]], 1):
                if positions == case:
                    result.append([i, k])
                    break
            else:
                result.append([i, k + 1])

    return result

Re: Überprüfung wie viele items in set

Verfasst: Dienstag 8. September 2015, 08:57
von schneitzmaster
Hallo BlackJack,

danke für die Hinweise. Ich hatte einen Tipfehler und den jetzt im Eingangspost behoben. Es muss natürlich

Code: Alles auswählen

hauptliste = set(hauptliste)
heißen.
Desweiteren danke ich auch für die Namensvorschläge. Ich tu mich immer schwer treffende Variablennamen zu finden. Die werden meist sehr lang. Aus diesem Grund habe ich auch nicht result sonder die Kurzform rslt benutzt. Die entsprechenden Befehle / Zeilen in meinem Code werden halt schnell lang und um noch im 80-Zeichen-pro-Zeile-Limit zu bleiben habe ich mir angewöhnt soweit es geht mit abkürzungen zu arbeiten. Klar mit 'sub_listen' stimme ich dir auch voll zu. Allerdings finde ich ist es leicher im Code 'sub_liste_i' zu erkennen als zwischen 'sub_listen' und 'sub_liste' zu differenzieren.

Re: Überprüfung wie viele items in set

Verfasst: Dienstag 8. September 2015, 09:09
von schneitzmaster
@BlackJack:
bei deinem ersten Post kann ich die For-Schleife noch mit

Code: Alles auswählen

anzahl = np.sum(uebereinstimmung,axis=1)
umgehen