2016-02-22 2 views
5

Ich habe eine Liste von Tupeln, die mit der zip-Funktion erstellt wird. zip bringt vier Listen zusammen: narrative, subject, activity und filer, von denen jede nur eine Liste von 0s und 1s ist. Sagen wir, die vier Listen wie folgt aussehen:Filtern Sie ein Tupel mit einem anderen Tupel in Python

narrative = [0, 0, 0, 0] 
subject = [1, 1, 0, 1] 
activity = [0, 0, 0, 1] 
filer = [0, 1, 1, 0] 

Nun, ich bin zip ing sie zusammen eine Liste der Boolesche Werte zu erhalten, die angibt, ob einer von ihnen True sind.

ny_nexus = [True if sum(x) > 0 else False for x in zip(narrative, subject, activity, filer)]

Das Problem, das ich jetzt mit bin, eine zweite Liste von Tupeln, für die immer die Namen der Variablen zurückgegeben, wenn es ein 1 während der Iteration hat. Ich stelle mir es so etwas wie folgt aussehen:

variables = ("narrative", "subject", "activity", "filer") 
reason = [", ".join([some code to filter a tuple]) for x in zip(narrative, subject, activity, filer)] 

Ich kann einfach nicht herausfinden, wie ich über diese gehen würde. Meine gewünschte Ausgabe würde wie folgt aussehen:

reason 
# ["subject", "subject, filer", "filer", "subject, activity"] 

Ich bin ein wenig neu zu Python, so dass ich entschuldige mich, wenn die Lösung einfach ist.

+1

Übrigens kannst du sagen 'ny_nexus = [Summe (x)> 0 für x in Zip ...]' – zondo

+0

Immer mehr prägnanten Code zu schätzen wissen. Danke – brittenb

+1

Noch besser, benutze die 'any()' eingebaute Funktion;) 'any ([0, 0, 0]) == False',' any ([0, 1, 0]) == True'. Also, 'ny_nexus = [any (x) für x in zip ...]' – AkiRoss

Antwort

3

Shop Tupeln in einem Wörterbuch für eine saubere Lösung:

tups = {'narrative': narrative, 
     'subject': subject, 
     'activity': activity, 
     'filer': filer} 

Die Lösung:

reason = [', '.join(k for k, b in zip(tups, x) if b) for x in zip(*tups.values())] 

Es kann auch sein, geschrieben mit itertools.compress :

from itertools import compress 
reason = [', '.join(compress(tups, x)) for x in zip(*tups.values())] 

Lösungen über Sie die Reihenfolge der Tupel nicht erhalten, z.B.sie können wie etwas zurückgeben

['subject', 'filer, subject', 'filer', 'activity, subject'] 

Wenn Sie den Auftrag zu erhalten müssen, verwenden Sie collections.OrderedDict wie unten dargestellt:

from collections import OrderedDict 

tups = OrderedDict([ 
    ('narrative', narrative), 
    ('subject', subject), 
    ('activity', activity), 
    ('filer', filer) 
]) 

# The result is ['subject', 'subject, filer', 'filer', 'subject, activity'] 

EDIT: Die Lösung, die nicht Wörterbücher mit sich bringt:

from itertools import compress 
reason = [', '.join(compress(variables, x)) 
      for x in zip(narrative, subject, activity, filer)] 

Verwenden Sie Wörterbücher, wenn die zip(...) Anruf passt nicht mehr in eine Zeile.

+0

So weit , das ist die einzige Lösung, die funktioniert. Es ist jedoch diejenige, die ich am wenigsten verstehe. Können Sie erklären, was 'compress' tut und was die Rolle' * 'in' zip (* tups.values ​​()) spielt? – brittenb

+0

@vaultah: Ich sehe nicht, wie ein Wörterbuch oder OrderedDict es sauberer macht. Du hast bereits 'compress()', warum fütterst du es nicht einfach mit '' variables' 'Tupel von OP? –

+0

@brittenb: Wenn Sie sich die Dokumentation für 'compress()' ansehen, werden Sie sehen, dass es genau das tut, wonach Sie suchen. Es wählt Elemente einer Sequenz basierend darauf aus, ob die entsprechenden Elemente einer anderen Sequenz wahr sind. –

0

Sie können nur die Filterung Aspekt der Verständnis Syntax Ihre vaiable englischen Namen, wenn das jeweilige Flag Wahr ist nur zu erhalten: geht es um Ihren Ansatz fischig dort etwas sagte,

variables = ("narrative", "subject", "activity", "filer") 
[tuple (name for flag, name in zip(x, variables) if x) for x in zip(narrative, subject, activity, filer)] 

das - Sie‘ Mit einem objektorientierten Ansatz ist es wahrscheinlich (viel) besser, anstatt zu versuchen, unabhängige Variablenfolgen für jedes Ihrer Subjekte manuell zu koordinieren.

+0

Dieser Ansatz ist für mich sinnvoll, aber da 'x' immer als Truthy ausgewertet wird, gibt es alle Werte in' variables' zurück. Können Sie Ihren objektorientierten Ansatz näher ausführen? Ich bin nicht so verheiratet wie ich es momentan mache und bin immer bereit neue Methoden auszuprobieren. – brittenb

0
narrative = [0, 0, 0, 0] 
    subject = [1, 1, 0, 1] 
    activity = [0, 0, 0, 1] 
    filer = [0, 1, 1, 0] 
    variables = ("narrative", "subject", "activity", "filer") 
    ny_nexus = [True if sum(x) > 0 else False for x in zip(narrative, subject, activity, filer)] 
    output = [] 
    [[output.append(variables[j]) if t==1 else None for j,t in enumerate(x)] for x in zip(narrative, subject, activity, filer)] 
    print ny_nexus 
    print output 

Natürlich können Sie nur folgendes zu tun ohne Listenkomprehensionen mit:

narrative = [0, 0, 0, 0] 
    subject = [1, 1, 0, 1] 
    activity = [0, 0, 0, 1] 
    filer = [0, 1, 1, 0] 
    variables = ("narrative", "subject", "activity", "filer") 
    ny_nexus = [True if sum(x) > 0 else False for x in zip(narrative, subject, activity, filer)] 
    output = [] 
    for x in zip(narrative, subject, activity, filer): 
     for j,t in enumerate(x): 
      output.append(variables[j]) 
    print ny_nexus 
    print output 
+0

Dieser Ansatz ist auch für mich sinnvoll, aber er gibt für alle Werte "None" zurück. Irgendeine Idee warum? – brittenb

+0

Die Ergebnisse von ny_nexus im obigen Code sind tatsächlich nutzlos. Die nützlichen Ergebnisse sind nur in der Ausgabe. In der Tat könnten Sie den Namen von ny_nexus in tmp oder etwas ändern und ignorieren. Der obige Code wäre zusätzlich zu Ihrer folgenden Aussage erforderlich: ny_nexus = [Wahr wenn Summe (x)> 0 sonst Falsch für x in zip (Erzählung, Thema, Aktivität, Filer)] – Sid

+0

Aktualisierte Antwort zu reflektieren – Sid

1

Mit zip(narrative, subject, activity, filer) transponiert im Grunde die Matrix (Liste der Listen gleicher Länge der Matrix bilden). Sie listen dann durch diese auf, um die Position n zu finden, in der das Flag wahr ist, und indizieren die entsprechende Variable.

narrative = [0, 0, 0, 0] 
subject = [1, 1, 0, 1] 
activity = [0, 0, 0, 1] 
filer = [0, 1, 1, 0] 
variables = ("narrative", "subject", "activity", "filer") 
# ======================================================== 

new_list = [[variables[n] for n, flag in enumerate(indicators) if flag] 
      for indicators in zip(narrative, subject, activity, filer)] 
>>> new_list 
[['subject'], ['subject', 'filer'], ['filer'], ['subject', 'activity']] 

Um zu sehen, die Transponierung:

>>> [i for i in zip(narrative, subject, activity, filer)]