Python Forum
How to check if class instance exists in a list of class instance objects?
Thread Rating:
  • 1 Vote(s) - 1 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to check if class instance exists in a list of class instance objects?
#11
(May-25-2018, 06:39 PM)buran Wrote: If need to keep order buran dictionary(3.6+) will do that.
not sure if that's at me, but what I wanted to say is that given list [person1, person2, person3] if we use dict, at the end we will have
[person3, person2] (in that order in python 3.6, and [possibly] reversed in python2 and python3 before 3.6), i.e. person3 would replace person1 as value for key 'John'.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#12
(May-25-2018, 06:39 PM)buran Wrote: at's unique person names list, but OP wants unique list of instances
Good point,did just took a quick look before i answered.
Your explanation with dict order(3.6) from list sound correct,
did a test with 2.7 and 3.4,then 3.6 and it did follow your explanation.
Reply
#13
(May-25-2018, 07:48 PM)snippsat Wrote: did a test with 2.7 and 3.4,then 3.6 and it did follow your explanation.
because original order comes from the list, not a dict... probably you just overlooked that
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#14
If the original list is instances and the resulting list is unique_instances, the following code will work without any tweaks to member classes

classes = set()
unique_instances = []
for instance in instances:
    if instance.__class__ not in clases:
        classes.add(instance.__class__)
        unique_instances.append(instance)
PS in general, I prefer to avoid using dunder attributes in regular code, but sometimes it's the easiest way.
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#15
The set() is the easiest solution. As mentioned before, the set does not preserve the order.
Since Python 3.6 the order of keys in dicts is preserved and in 3.7 it's a definition of the language.


unique_set = set(your_list) # no order!
unique_dict = list(dict.fromkeys(your_list).keys())

# pre 3.6
import collections
ordered_dict = list(collections.OrderedDict.fromkeys(your_list).keys())
The dict and the OrderedDict do have alternative init methods.
Both have the fromkeys Classmethod. This means,
that you can make a dict, with only keys. The values are None, if you don't
define them differently in the method call. But in your case, you only need the keys.
We misuse the fact, that a dictionary (HashTable) can have only unique keys.

A set is mostly the same, only the values are not stored and since Python 3.6 they are still not ordered as dicts in Python 3.6. But I guess they never change it.

If you have time, look into the documentation about set().
It's an important data structure and a shortcut for many tasks.
To have unique elements is only one possbile task.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#16
@volcano63 and @DeaD_EyE, note that we are talking about custom calss that does not inherit from standard python classes.
using set requires it to be hashable, thus I suggested implementing special metods. OP thinks it's overkill for their purposes.javascript:;
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#17
(May-26-2018, 03:14 PM)buran Wrote: note that we are talking about custom class that does not inherit from standard python classes.

AFAIK, every class in Python inherits from object - which is pretty standard. I presume that one can define a class that is not hashable - class, not instance - but i will take some hacking. So I think that your warning is of little merit.

(May-26-2018, 01:25 PM)DeaD_EyE Wrote: The set() is the easiest solution. As mentioned before, the set does not preserve the order.
Since Python 3.6 the order of keys in dicts is preserved and in 3.7 it's a definition of the language.

unique_set = set(your_list) # no order!
unique_dict = list(dict.fromkeys(your_list).keys())

# pre 3.6
import collections
ordered_dict = list(collections.OrderedDict.fromkeys(your_list).keys())

And this solves OP's problem how? The intent is to preserve only one instance per class in the list

PS It seems that I misinterpreted the question
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#18
(May-26-2018, 07:31 PM)volcano63 Wrote: AFAIK, every class in Python inherits from object - which is pretty standard. I presume that one can define a class that is not hashable - class, not instance - but i will take some hacking. So I think that your warning is of little merit.

class Person:
    def __init__(self, name):
        self.name =  name

person1 = Person('John')
person2 = Person('John')

persons = [person1, person2]
print(set(persons))
In python3 and python2 the output will be
Output:
{<__main__.Person object at 0x7ff9a43b6828>, <__main__.Person object at 0x7ff9a43b6860>}
so virtually, OP cannot do what they want with set

if there is __eq__() implemented
class Person:
    def __init__(self, name):
        self.name =  name

    def __eq__(self, other):
        return self.name == other.name

person1 = Person('John')
person2 = Person('John')

persons = [person1, person2]
print(set(persons))
in python2
Error:
Traceback (most recent call last): File "/home/boyan/Desktop/f.py", line 12, in <module> print(set(persons)) TypeError: unhashable instance
in python3:
Error:
File "/home/boyan/Desktop/f.py", line 12, in <module> print(set(persons)) TypeError: unhashable type: 'Person'
again, not possible to use set
Also note that even some 'standard' classes like list are not hashable
list1 = [1,2,3]
list2 = [5,6,7]
print(set([list1,list2]))
Error:
Traceback (most recent call last): File "/home/boyan/Desktop/f.py", line 3, in <module> print(set([list1,list2])) TypeError: unhashable type: 'list'
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#19
As I have mentioned above, I answered the wrong question - not the one that was asked - so consider me downvoted Blush

Nevertheless, there's no need for special methods

seen_names = set()
unique_names = []
for instance in mylist:
    name = vars(instance)['name']
    if name not in seen_names:
        seen_names.add(name)
        unique_names.append(instance)
BTW set is applied only to attribute (in the previous comment - to class object) - so @DeaD_EyE's worries were for nothing, the order is preserved

@buran, would you do me a favor and re-read my answer? Set contained instances of classes, not instances of objects
classes.add(instance.__class__)

Output:
In [28]: hash(dict().__class__) Out[28]: 646488 In [29]: hash(list().__class__) Out[29]: 645854

PS Obviously, I am not the only inattentive reader around Doh
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#20
maybe I should have used unhashable type (as per the Traceback)

(May-26-2018, 08:04 PM)volcano63 Wrote: Set contained instances of classes, not instances of objects

instances of classes and instances of objects???
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How does this code create a class? Pedroski55 6 447 Apr-21-2024, 06:15 AM
Last Post: Gribouillis
  class definition and problem with a method HerrAyas 2 271 Apr-01-2024, 03:34 PM
Last Post: HerrAyas
  Printing out incidence values for Class Object SquderDragon 3 305 Apr-01-2024, 07:52 AM
Last Post: SquderDragon
  class and runtime akbarza 4 401 Mar-16-2024, 01:32 PM
Last Post: deanhystad
  Help with to check an Input list data with a data read from an external source sacharyya 3 422 Mar-09-2024, 12:33 PM
Last Post: Pedroski55
  Operation result class SirDonkey 6 571 Feb-25-2024, 10:53 AM
Last Post: Gribouillis
  The function of double underscore back and front in a class function name? Pedroski55 9 685 Feb-19-2024, 03:51 PM
Last Post: deanhystad
  super() and order of running method in class inheritance akbarza 7 781 Feb-04-2024, 09:35 AM
Last Post: Gribouillis
  Class test : good way to split methods into several files paul18fr 4 494 Jan-30-2024, 11:46 AM
Last Post: Pedroski55
  Good class design - with a Snake game as an example bear 1 1,848 Jan-24-2024, 08:36 AM
Last Post: annakenna

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020