Donnerstag, Juni 4, 2020

Liste und erfassen, überprüfen, wenn das Einzelteil ist einzigartig

Ich bin versucht zu schreiben, eine Liste Verständnis statement, das nur ein Element hinzufügen, wenn Sie derzeit nicht in der Liste enthalten. Gibt es eine Möglichkeit zu prüfen, die aktuelle Elemente in der Liste, die gerade aufgebaut wird? Hier ist ein kurzes Beispiel:

Eingang

{
    "Stefan" : ["running", "engineering", "dancing"],
    "Bob" : ["dancing", "art", "theatre"],
    "Julia" : ["running", "music", "art"]
}

Ausgabe

["running", "engineering", "dancing", "art", "theatre", "music"]

Code ohne Verwendung einer Liste Verständnis

output = []
for name, hobbies in input.items():
    for hobby in hobbies:
        if hobby not in output:
            output.append(hobby)

Mein Versuch

[hobby for name, hobbies in input.items() for hobby in hobbies if hobby not in ???]
  • Erwägen Sie die Verwendung ein, anstatt, wie es eliminiert Duplikate automatisch für Sie.
  • Ich könnte die Ausgabe der Liste Verständnis in der set () – Konstruktor, aber ich Frage mich ob es einen Weg gibt, dies zu tun, nur mit list comprehension
  • Sie missbrauchen könnte yield from in Python ist3.3+ zu vermeiden, double-loop: set([(yield from x) for x in d.values()]). Beachten Sie, dass dies s=set((yield from x) for x in d.values()) Erträge fast die gewünschte Ausgabe… es enthält eine zusätzliche None, die Sie entfernen müssen, so s.discard(None). (Ich glaube, es gibt schon eine Frage zu diesem Unterschied im Verhalten zwischen gen exps und Liste-Verstehens).

8 Kommentare

  1. 34

    Können Sie set – und set-comprehension:

    {hobby for name, hobbies in input.items() for hobby in hobbies}

    Als m.wasowski erwähnt, wir verwenden nicht die name hier, so können wir item.values() statt:

    {hobby for hobbies in input.values() for hobby in hobbies}

    Wenn Sie wirklich brauchen, eine Liste als Ergebnis, Sie können dies tun (aber beachten Sie, dass in der Regel können Sie arbeiten mit sets ohne problem):

    list({hobby for hobbies in input.values() for hobby in hobbies})
    • Ich nehme an, es ist nicht einmal Grund, es zu konvertieren zurück in eine Liste. Wahrscheinlich würde die Liste werden, ein set-Konzept sowieso.
    • Ich habe nur Hinzugefügt, weil der OP hatte seinen Ausgang in einer Liste und er könnte einige Besondere Grund, warum er braucht eine Liste. In den meisten Fällen sind Sie natürlich Recht.
    • Sie können input.values() wenn Sie kümmern sich nicht um Namen
    • Danke, du hast Recht. Ich ‚ ll fügen Sie es in die Antwort.
    • Kann jemand zu Fuß durch die Mitte begreifen, so kann ich sehen, wie „hobby“ und „Hobbys“ get definiert? Ich bin mir nicht ganz klar über die Reihenfolge der Ausführung hier. Danke.
    • Gut.. Die ersten hobbies sind definiert als die Listen von Hobbys, die in input.values() (d.h. eine Liste von Listen von Hobbys). Dann werden diese Listen iteriert durch die for hobby in hobbies – hier hobbies ist eine Nutzung der hobbies definiert durch hobbies in input.values(). Die zweite hobby ist daher definiert als jeder hobby in jedem hobbies Liste (one by one). Die ersten hobby ist dann eine Verwendung solcher definiert Hobbys, und jedes solches hobby ist Hinzugefügt, um die Ergebnismenge. Damit jedes hobby ist in der Folge einmal (denn es ist ein set). Ist es klarer jetzt? Ich hoffe, ich habe nicht noch schlimmer machen.
    • kann der dual ‚für‘ die syntax in das Verständnis erweitert werden, um im Fall von einigen-Funktion fun von hobby? {fun(hobby) for hobbies in input.values() for fun(hobby) in hobbies}. Läuft in SyntaxError mit diesem Ansatz. Und wenn nicht, gibt es eine alternative?
    • für Hobbys in-Eingang.Werte() für hobby Hobbys} sollte funktionieren.

  2. 16

    Als diese Antwort – Idee: Sie können eine Einzigartigkeit filter:

    def f7(seq):
        seen = set()
        seen_add = seen.add
        return [x for x in seq if not (x in seen or seen_add(x))]

    und rufen mit:

    >>> f7(hobby for name, hobbies in input.items() for hobby in hobbies)
    ['running', 'engineering', 'dancing', 'art', 'theatre', 'music']

    Ich würde implementieren, die Einzigartigkeit filter getrennt, da eine design-Regel sagt „verschiedene Dinge behandelt werden sollten, die durch verschiedene Klassen/Methoden/Komponenten/was auch immer“. Darüber hinaus können Sie einfach wiederverwenden Sie diese Methode, wenn nötig.

    Ein weiterer Vorteil ist – wie ist geschrieben in der verlinkte Antwort -, dass die um der Elemente wird beibehalten. Für einige Anwendungen notwendig sein könnten.

    • noch besser, wenn Sie drop die eckigen Klammern
    • geändert, besser?
    • Punkte für die Aufrechterhaltung der Ordnung.
    • Wirklich der einzige Grund zu gehen, ist ein Ansatz wie das wäre, wenn Sie sich über die Reihenfolge, in der die ursprünglichen Elemente erschienen. Aber selbst dann würde ich mich sehr freuen, mit einer Liste Verständnis haben Nebenwirkungen.
    • die Nebenwirkungen auf die Liste Verstehens sind lokal seit die einzigen beteiligten Variablen werden in der Methode selbst.
    • IMO dies ist mehr lesbar, wenn das Prädikat steht geschrieben, wie if x not in seen and seen.add(x) is None
    • Ich bin damit einverstanden, aber wenn Sie Folgen Sie dem link auf die Antwort, die Sie werden sehen, es gibt einen bestimmten Grund: durch abkürzens der Verweis auf die Methode, die den Zugriff auf die Methode ist schneller, was in einem oder zwei Millisekunden zusätzliche Leistung. Wenn Sie anrufen seen.add ist es möglich (im Allgemeinen, nicht in diesem Fall), dass die seen.add geändert wird zwischen zwei Anrufe. Python hat damit führen Sie eine weitere Suche.
    • Oh I don ‚ T care über die Lokalisierung des add-Methode, das war nicht, was mein Kommentar war um, und ich weiß lokalisieren Dinge die ganze Zeit, wenn ich fahre für Geschwindigkeit, aber ich würde im Hinterkopf behalten, dass die vorzeitige Optimierung ist die Wurzel allen übels.
    • Wahr, aber (a) python-Verknüpfungen, Boolesche schaltkreise, und implizit sagt es not (seen.add(x) is None) für den zweiten Teil sowieso und (b) kann man kaum sagen, das ist vorzeitige – Optimierung, da dies eine utility-Funktion. 😉
    • Fair genug, sir, ich von Ihnen positiv bewertet werden Ihre Antwort sowieso, weil ich denke, es ist besser als das akzeptiert man aufgrund der Aufrechterhaltung der Ordnung. @ThijsvanDien Was ist falsch mit einer Liste Verständnis mit Nebenwirkungen? Es ist so ziemlich dasselbe wie eine for-Schleife mit Nebenwirkungen.

  3. 7

    sets und dictionaries sind deine Freunde hier:

    from collections import OrderedDict
    from itertools import chain # 'flattens' collection of iterables
    
    data = {
        "Stefan" : ["running", "engineering", "dancing"],
        "Bob" : ["dancing", "art", "theatre"],
        "Julia" : ["running", "music", "art"]
    }
    
    # using set is the easiest way, but sets are unordered:
    print {hobby for hobby in chain.from_iterable(data.values())}
    # output:
    # set(['art', 'theatre', 'dancing', 'engineering', 'running', 'music'])
    
    
    # or use OrderedDict if you care about ordering:
    print OrderedDict(
            (hobby, None) for hobby in chain.from_iterable(data.values())
        ).keys()
    # output:
    # ['dancing', 'art', 'theatre', 'running', 'engineering', 'music']
    • Die OrderedDict Methode ist die, die ich wählen würde, hier.
    • Ich glaube deine Antwort sollte verdeutlichen, was du meinst mit der „Bestellung“: Als data ist ein normales Wörterbuch, Sie die resultierende Reihenfolge der Aufruf data.values() ist willkürlich. Dadurch ist die Reihenfolge der keys() im OrderedDict betrachtet werden teilweise willkürlich als gut. Die Listen sind zufällig sortiert (in deinem Fall die Reihenfolge der Listen wurden diejenigen von: Bob, Stefan, Julia), aber Ihre Elemente‘ Aufträge erhalten. Aufgrund von überschneidungen kann dies dazu führen, ganz andere Aufträge.
  4. 7

    Wenn Sie wirklich, wirklich wollen, eine listcomp und nur eine Liste-comp, die Sie tun können,

    >>> s = []
    >>> [s.append(j)  for i in d.values() for j in i if j not in s]
    [None, None, None, None, None, None]
    >>> s
    ['dancing', 'art', 'theatre', 'running', 'engineering', 'music']

    Hier s ist das Ergebnis einer Nebenwirkung und d ist Ihre original-Wörterbuch. Der eindeutige Vorteil hier ist, dass bewahren Sie die Reihenfolge, im Gegensatz zu den meisten anderen Antworten hier.

    Hinweis: Dies ist ein schlecht Weg, wie es exploits die Liste-comp und das Ergebnis ist ein Nebeneffekt. Tun Sie es nicht als eine Praxis, Diese Antwort ist nur um Ihnen zu zeigen, dass Sie es erreichen können mit Hilfe einer list comp allein

    • Ugh.. Diese Art der Lösung können Sie nicht entmutigt genug.
    • Ich habe es syntaktisch mehr betont, so dass die meisten Personen fangen die Warnung.
    • noch schlimmer sind diejenigen, die unnötige verschachtelte Verstehens
    • Sie sind alle erforderlich. Sie bieten eine Alternative Lösung. Ich werde mehr als glücklich sein, hinzufügen, dass. TIA für deine Antwort
    • itertools.chain.from_iterable – wie ich in meiner Antwort
    • O c ‚ Mon bro! 1. Ich wollte die Antwort in einer Weise, die nicht beantwortet wurde, vor 2. Ich wartete für jemanden, der zum hinzufügen von itertools Antwort. 3. Das ist reines python ohne Importe. Deine Antwort ist gut, kein Zweifel
    • die standard-Bibliothek ist nicht in der ‚reinen python‘? C ‚ Mon… mit standard-Module, die gefördert werden sollte. Und es ist die bevorzugte Lösung für verschachtelte Verständnis, geschweige denn die einzelnen Buchstaben Variablen-Namen,…
    • Wahr ist, dass Ihre die bessere Lösung ist. Dies ist eine alternative nur. Alle zukünftigen Benutzer werden sicherlich Ihre Antwort vor mir. So werden Sie lernen, eine Alternative Methodologie zu. Ich bin damit einverstanden, dass dies kein guter Weg ist und ich gesagt habe es von der zweiten habe ich es geschrieben als Antwort. Für die einzelnen Buchstaben für Variablennamen. Ich weiß, dass Sie nicht in übereinstimmung mit PEP. Aber es schadet nicht, hier ist es der 6. beantworten Sie unten in der Liste. Allerdings, wenn Sie immer noch das Gefühl, dass diese Antwort sollte nicht hier sein, vergessen Sie es. Ich werde es löschen mit einem Hinweis auf künftige Zuschauer über 10k. Nochmals vielen Dank!
    • Ich denke, das Modell der SO ist one-to-many Beziehungen von Fragen zu beantworten, die jeweils mit (dis -) Vorteile. Solange es genug Warnungen, die auch ein “ worst-case exponentiell mit der Zeit annehmbare Lösung ist. Die voting system wird verwendet, um (a) filter aus falschen Antworten und (b) Rang Antworten für die praktische Anwendung.
    • Ach du meine Güte… sorry für den Ausdruck meiner Meinung nach 😉 ich werde nicht fallen banhammer auf Euch Jungs trotzdem, wirklich! @Bhargav Rao – natürlich halten deine Antwort – macht weiter einen guten job Beantwortung von Menschen hier. Sorry, wenn meine Kommentare waren die zu hart, ich wollte nicht.
    • Man braucht wirklich nicht traurig sein hier! Der einzige Punkt ist, dass, wenn diese Antwort war die erste oder die zweite oder eine FGITW dann ist es sicherlich nicht hier hingehört. Das timing der Antwort ist auch wichtig. Eine schlechte Antwort, die angibt, warum es schlecht ist hilft auch die künftigen Nutzer nicht von der Nutzung dieser Taktik, Ihre Probleme zu lösen. Ich hoffe, mit diesem Hinweis alle Stände geräumt! Noch einen schönen Tag. 🙂

  5. 6

    Gibt es einen anderen Weg dies zu schreiben, dass ist ein bisschen mehr beschreiben, was Sie eigentlich tun, und nicht einen verschachtelten (Doppel –for) Verständnis:

    output = set.union(*[set(hobbies) for hobbies in input_.values()])

    Diese wird noch schöner, wenn Sie würden repräsentieren die Eingabe, um mehr konzeptionell solide sind, D. H. die Nutzung setzt sich für die Hobbys der jeweiligen person (seit es sollte keine Wiederholungen gibt):

    input_ = {
        "Stefan" : {"running", "engineering", "dancing"},
        "Bob" : {"dancing", "art", "theatre"}, 
        "Julia" : {"running", "music", "art"}
    }
    
    output = set.union(*input_.values())
    • für mich die beste Lösung, die von weit
  6. 5

    Einer list comprehension ist nicht gut geeignet für dieses problem. Ich denke, ein set Verständnis wäre besser, aber da war schon in einer anderen Antwort, ich zeige einen Weg, dieses problem zu lösen mit einem kompakten one-liner:

    list(set(sum(hobbies_dict.values(), [])))

    Andere interessante Lösung mit dem bitweisen oder-operator dient als union-operator für Mengen:

    from operator import or_
    from functools import reduce # Allowed, but unnecessary in Python 2.x
    list(reduce(or_, map(set, hobbies_dict.values())))

    Oder (unbeabsichtigtes Wortspiel, ich schwöre), anstelle der Verwendung der bitweisen oder-operator, verwenden Sie einfach set.union übergeben und ausgepackt festlegen-Zuordnung der Werte. Keine Notwendigkeit zu importieren or_ und reduce! Diese Idee ist inspiriert von Thijs van Dien Antwort.

    list(set.union(*map(set, hobbies_dict.values())))
  7. 4

    Satz:

    dict = {
        "Stefan" : ["running", "engineering", "dancing"],
        "Bob" : ["dancing", "art", "theatre"],
        "Julia" : ["running", "music", "art"]
    }
    
    myset = set()
    for _, value in dict.items():
        for item in value:
            myset.add(item)
    
    print(myset)
  8. 4

    Wie wäre es damit:

    set(dict['Bob']+dict['Stefan']+dict['Julia'])
    >>> set(['art', 'theatre', 'dancing', 'engineering', 'running', 'music'])

    Oder mehr schön:

    dict = {
        "Stefan" : ["running", "engineering", "dancing"],
        "Bob" : ["dancing", "art", "theatre"],
        "Julia" : ["running", "music", "art"]
    }
    
    list_ = []
    for y in dict.keys():
        list_ = list_ + dict[y]
    list_ = set(list_)
    >>> list_
    set(['art', 'theatre', 'dancing', 'engineering', 'running', 'music'])

    können Sie die list Funktion list_ wie list(list_) um eine Liste statt einen Satz.

Kostenlose Online-Tests