2011-12-23 14 views
12

Si tengo un objeto que se compare con un elemento de un conjunto Python, pero no es el mismo objeto, ¿hay alguna forma razonable de obtener una referencia al objeto en el conjunto? El caso de uso usaría el conjunto para identificar y compartir datos duplicados.¿Cómo acceder a un elemento de un conjunto usando un objeto equivalente?

Ejemplo (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 

Cómo obtener una referencia al uso de ab y s? Puedo pensar de una manera, pero no estoy seguro si no depende de la implementación si obtiene a o b. EDITAR: Esto no funciona cuando s tiene más de un elemento; intersección se implementó bastante naturalmente algo así como [x for x in smaller_set if x in larger_set]

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

Tal vez una buena solución sería utilizar un diccionario que mapea cada clave a sí mismo, en lugar del conjunto.

+2

Si necesita uno específico de dos objetos iguales y con capacidad de manipulación, es probable que los objetos no sean iguales y/o no puedan manipularse. ¿Por qué necesitas esto? – delnan

+0

Creo que sus sospechas están justificadas: pypy 1.7.0 y ironpython 3.0 ambos (pueden) devolver False para su c final es a. – DSM

+0

Podría ahorrar memoria cambiando las referencias al objeto igual a las referencias al mismo objeto. –

Respuesta

3

Encontré una pregunta similar en python-list: Get item from set. Hay una respuesta inteligente con referencia a get_equivalent(container, item) (Python recipe).

El truco consiste en construir un objeto envoltorio para el objeto 'clave', y verificar si el envoltorio está en el conjunto usando el operador in. Si los valores hash de envoltura son iguales a la clave, su método __eq__ puede obtener acceso al objeto en el conjunto y guardar una referencia al mismo. Un punto importante de la discusión es que el método __eq__ de los elementos establecidos debe devolver NotImplemented para los tipos no reconocidos, de lo contrario no se puede llamar al contenedor __eq__.

1

Su caso de uso parece que es un caso de uso para los diccionarios. Utilice, como claves, el atributo del objeto que se compare con el objeto "extraño", y como valores los objetos deseados.

Si se trata de un caso de uso simple, y se puede tener una seartch lineal, sin embargo, se puede hacer lo obvio - que no sería mala:

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

Si necesita qué es exactamente lo que usted ar pidiendo para (me puedo preguntar algunos casos de uso para eso) - el wya para ir es crear una clase de diccionario personalizada que tiene un conjunto como uno de sus miembros, implementar metodos de proxy para el conjunto de miembros, y en ambos métodos de diccionario y establecer, mantiene la sincronización tanto del diccionario como del contenido. Esto llevaría mucho tiempo implementarlo correctamente, pero relativamente sencillo.

Cuestiones relacionadas