2011-12-23 18 views
12

Se ho un oggetto che confronta uguale a un elemento di un set Python, ma non è lo stesso oggetto, c'è un modo ragionevole per ottenere un riferimento all'oggetto nel set? Il caso d'uso userebbe il set per identificare e condividere dati duplicati.Come accedere ad un elemento di un set usando un oggetto equivalente?

Esempio (Python 2.7):

>>> a = "This is a string" 
>>> b = "This is a string" 
>>> a is b 
False 
>>> a == b 
True 
>>> s = set((a,)) 
>>> b in s 
True 

Come ottenere un riferimento a a utilizzando b e s? Posso pensare a un modo, ma non sono sicuro che non dipenda dall'implementazione se ricevi a o b. EDIT: Questo non funziona quando s ha più di un elemento; intersezione viene del tutto naturale implementato qualcosa di simile [x for x in smaller_set if x in larger_set]

>>> for x in set((b,)).intersection(s): c = x 
... 
>>> c is a 
True 

Forse una buona soluzione alternativa sarebbe quella di utilizzare un dict che mappa ogni tasto a se stesso, al posto del set.

+2

Se è necessario uno specifico di due oggetti uguali e lavabili, è probabile che gli oggetti non siano uguali e/o lavabili. Perchè ti serve? – delnan

+0

Penso che i tuoi sospetti siano giustificati: pypy 1.7.0 e ironpython 3.0 entrambi (can) return False per la tua c finale è a. – DSM

+0

Potrei risparmiare memoria cambiando i riferimenti a oggetti uguali a riferimenti allo stesso oggetto. –

risposta

3

Ho trovato una domanda simile su python-list: Get item from set. C'è una risposta intelligente con riferimento a get_equivalent(container, item) (Python recipe).

Il trucco consiste nel costruire un oggetto wrapper per l'oggetto 'chiave' e controllare se il wrapper si trova nel set utilizzando l'operatore in. Se il wrapper hash uguale alla chiave, il suo metodo __eq__ può accedere all'oggetto nel set e salvare un riferimento ad esso. Un punto importante della discussione è che il metodo __eq__ degli elementi impostati deve restituire NotImplemented per i tipi non riconosciuti, altrimenti il ​​__eq__ del wrapper potrebbe non essere richiamato.

1

Il caso d'uso sembra un caso d'uso per i dizionari. Usa, come chiavi, l'attributo dell'oggetto che confronta uguale all'oggetto "straniero" e come valori gli oggetti desiderati stessi.

Se si tratta di un semplice caso d'uso, e si può avere un seartch lineare, tuttavia, si potrebbe fare l'ovvio - non sarebbe male:

def get_equal(in_set, in_element): 
    for element in in_set: 
     if element == in_element: 
      return element 
    return None 

Se avete bisogno di che cosa esattamente quello che si ar chiedendo per (posso chiedermi alcuni casi d'uso per questo) - il wya da fare è creare una classe dizionario personalizzata che abbia un set come uno dei suoi membri, implementare mehthods proxy al set membro, e in entrambi i metodi dizionario e set, mantiene la sincronizzazione del dizionario e imposta i contenuti. Ciò richiederebbe molto tempo per implementare correttamente, ma relativamente semplice.

Problemi correlati