it-swarm.com.de

Pythonlistenverständnis für Wörterbücher in Wörterbüchern?

Ich habe gerade etwas über das Listenverständnis gelernt, mit dem sich Daten schnell in einer einzigen Codezeile abrufen lassen. Aber etwas nervt mich.

In meinem Test habe ich diese Art von Wörterbüchern in der Liste:

[{'y': 72, 'x': 94, 'fname': 'test1420'}, {'y': 72, 'x': 94, 'fname': 'test277'}]

Das Listenverständnis s = [ r for r in list if r['x'] > 92 and r['x'] < 95 and r['y'] > 70 and r['y'] < 75 ] funktioniert perfekt (es ist in der Tat das Ergebnis dieser Zeile)

Jedenfalls wurde mir dann klar, dass ich in meinem anderen Projekt nicht wirklich eine Liste verwende, sondern ein Wörterbuch. Wie so:

{'test1420': {'y': '060', 'x': '070', 'fname': 'test1420'}}

Auf diese Weise kann ich mein Wörterbuch einfach mit var['test1420'] = ... bearbeiten.

Aber Listenverständnisse funktionieren nicht! Und ich kann Listen nicht auf diese Weise bearbeiten, weil Sie einen solchen Index nicht zuweisen können.

Gibt es eine andere Art und Weise?

21
skerit

Du kannst das:

s = dict([ (k,r) for k,r in mydict.iteritems() if r['x'] > 92 and r['x'] < 95 and r['y'] > 70 and r['y'] < 75 ])

Dies nimmt ein Dikt wie angegeben und gibt ein "gefiltertes" Dikt zurück.

36
adamk

Wenn dct ist 

{'test1420': {'y': '060', 'x': '070', 'fname': 'test1420'},
 'test277': {'y': 72, 'x': 94, 'fname': 'test277'},}

Vielleicht suchen Sie nach etwas wie:

[ subdct for key,subdct in dct.iteritems() 
  if 92<subdct['x']<95 and 70<subdct['y']<75 ]

Ein wenig nett ist, dass Sie mit Python Ungleichheiten verketten können:

92<dct[key]['x']<95

anstatt

if r['x'] > 92 and r['x'] < 95

Beachten Sie auch, dass ich oben ein Listenverständnis geschrieben habe, so dass Sie eine Liste (in diesem Fall von Diktaten) zurückbekommen.

In Python3 gibt es solche Dinge wie Diktierverstehen ebenso:

{ n: n*n for n in range(5) } # dict comprehension
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

In Python2 wäre das Äquivalent 

dict( (n,n*n) for n in range(5) )

Ich bin nicht sicher, ob Sie nach einer Liste von Diktaten oder Diktaten suchen, aber wenn Sie die obigen Beispiele verstehen, können Sie leicht meine Antwort modifizieren, um das zu erhalten, was Sie möchten.

8
unutbu

Klingt wie Sie wollen etwas wie:

my_dict = {'test1420': {'y': '060', 'x': '070', 'fname': 'test1420'},
           'test277' : {'y': '072', 'x': '094', 'fname': 'test277'}}


new_dict = dict((k,v) for k,v in my_dict.items() 
                    if 92 < int(v['x']) < 95 and 70 < int(v['y']) < 75)

Einige Anmerkungen zu diesem Code:

  1. Ich verwende einen Generatorausdruck Anstelle eines Listenverständnisses
  2. In Python können Sie Ungleichheitstests (.____.) Als low < value < high kombinieren. 
  3. Der dict () - Konstruktor benötigt ein iterierbares Von Schlüssel-/Wert-Tupeln, um ein - Verzeichnis zu erstellen
2
Triptych

Mit d.values() erhalten Sie eine Liste der Werte eines Wörterbuchs d. Ihr Listenverständnis sollte damit funktionieren, obwohl ich etwas unklar bin, was genau die Ausgabe sein soll.

0
Rob Lourens

Gibt es eine andere Möglichkeit?

Warum sollten Sie nicht die Verwendung einiger leichter Objekte in Betracht ziehen? 

Sie können still List Comprehensions zum Sammeln oder Filtern der Objekte verwenden und viel an Klarheit/Erweiterbarkeit gewinnen.

>>> class Item(object):
...     def __init__(self, x, y, name):
...         self.x = x
...         self.y = y
...         self.name = name
... 
>>> list_items = []
>>> list_items.append(Item(x=70, y=60, name='test1420'))                        
>>> list_items.append(Item(x=94, y=72, name='test277'))                         
>>> items_matching = [item for item in list_items 
                      if 92 < item.x < 95 and 70 < item.y < 75]
>>> for item in items_matching:
...     print item.name
... 
test277
>>> first_item = items_matching[0]
>>> first_item.x += 50
>>> first_item.x
144
0
ChristopheD