2016-08-05 54 views
0

Ok, nicht sicher, ob das der beste Titel war, aber ich habe zwei Python-Listen. L1 und L2, die beide Elemente vom Typ T haben und nicht die gleiche Länge haben.Für zwei Listen, l1 und l2, wie man das für alle e1 ∈ l1, ∃p (e1, e2), wo e2 ist ein Element in l2, effizient in Python?

I eine Funktion p (T, T), das ein Prädikat eine Eigenschaft über zwei Elemente vom Typ T. Überprüfung

Ich mag würde, dass für alle Elemente e in L1 überprüfen, p (e, e ') hält, wo e' ist ein Element in L2. also gehe ich grundsätzlich für jedes Element in L1 über die zweite Liste und prüfe, ob das Prädikat für eines der Elemente gilt. Aber ich möchte das gleiche für die andere Liste überprüfen.

p (T, T) symmetrisch ist. Also wenn p (e, e ') dann p (e', e). Ich möchte das wegen dieser Symmetrie nicht zweimal machen. Ich muss irgendwie aufzeichnen, wenn ich p (e, e ') sehe, dann weiß ich p (e', e) und muss nicht noch einmal nach der zweiten Liste suchen.

Was ist der beste Weg, dies in Python zu tun? Ich dachte darüber nach, ein weiteres Feld für jedes Element e1 in jeder Liste zu haben, und teilte uns mit, ob p (e1, e2) gilt, wobei e2 ein Mitglied der anderen Liste ist. Aber ich denke, das erfordert das Kopieren beider Listen, damit ich sie nicht mutiere. Gibt es einen guten Weg, dies zu tun?

+0

Wenn Sie bereit sind, etwas precomputation zu tun, wie Sie vorschlagen, können Sie immer tun, um die Check-in O (1) Zeit für jedes Element von L1. Erstelle einfach zwei weitere Listen LL1 und LL2, so dass LL1 [i] == 1 genau dann, wenn für das i-te Element e1 von LL1 e1 in L2 existiert, so dass p (e1, e2). Sie können die Antwort auf die Gesamtfrage aufzeichnen (für alle e1 in L1 existiert ...) auch – Alejandro

+0

Ok, ich habe meine Frage mit diesem Code bearbeitet. Ich bin mir nicht sicher, ob das genau das ist, was du meintest, aber wenn es das ist, dann macht es für mich sehr viel Sinn. – Lana

+0

@Alejandro: Das spart wirklich keine Arbeit; Die Vorberechnung ist "O (n ** 2)", und es ist nicht sehr wiederverwendbar. – user2357112

Antwort

2

Die Tatsache, dass p symmetrisch ist, ist im wesentlichen nutzlos. Es ist wahr, dass, wenn Sie wissen, p(e, e') hält, wissen Sie p(e', e) hält, aber es sei denn e und e' beide sind in beiden Listen erhalten Sie nur Verwendung Ihrer Prädikat Auswertung machen einmal statt zweimal. Selbst wenn die Listen wahrscheinlich eine wesentliche Überlappung aufweisen, ist es möglicherweise effizienter, die Bewertungen zu wiederholen, als zu versuchen, die Symmetrie auszunutzen.

Der beste Weg, die gewünschte Überprüfung durchzuführen, wird wahrscheinlich die Reorganisation Ihrer Daten und die Nutzung einer weiteren Struktur von e beinhalten, um einen effizienteren Algorithmus zu finden, aber mit den Informationen, die wir haben, können wir Ihnen nicht helfen damit. Das Beste, was ich vorschlagen kann, ist rohe Gewalt:

def check(p, l1, l2): 
    for a in l1: 
     if not any(p(a, b) for b in l2): 
      return False 
    return True 
+0

Wie wäre es mit 'all (any (p (a, b) für b in l2) für a in l1)'? –

+0

@tobias_k: Ja, das würde funktionieren. – user2357112

0

ich für jede Liste ein Wörterbuch nur schaffen würde (dict1 und dict2 sein könnte), und wenn Sie durch die erste Liste iterieren, setzen Sie beide dict1[e] = e' und dict2[e'] = e. Dann, wenn Sie durch L2 iterieren, überprüfen Sie zuerst, dass die aktuelle e nicht in dict2 ist. Diese Überprüfung könnte auch zur ersten Iteration in L1 hinzugefügt werden, wenn doppelte Werte e vorliegen. Hoffe, das macht Sinn - schreibe das auf meinem Handy.

+0

"Sie setzen beide' dict1 [e] = e'' und 'dict2 [e '] = e'" - aber Sie wissen nicht, was 'e'' sein müsste, wenn Sie' e' oder umgekehrt betrachten versa. Wenn Sie das täten, gäbe es viel effizientere Möglichkeiten. – user2357112

+0

Ich dachte, OP fragte nur, wie man es vermeidet, erneut zu überprüfen, sobald er/sie e ' – Camsbury

+0

gefunden hat und weil es symmetrisch ist, e "ist e – Camsbury