Posts: 8,167
Threads: 160
Joined: Sep 2016
May-25-2018, 06:45 PM
(This post was last modified: May-25-2018, 06:45 PM by buran.)
(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'.
Posts: 7,324
Threads: 123
Joined: Sep 2016
May-25-2018, 07:48 PM
(This post was last modified: May-25-2018, 07:48 PM by snippsat.)
(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.
Posts: 8,167
Threads: 160
Joined: Sep 2016
(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
Posts: 566
Threads: 10
Joined: Apr 2017
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.
Posts: 2,128
Threads: 11
Joined: May 2017
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.
Posts: 8,167
Threads: 160
Joined: Sep 2016
May-26-2018, 03:14 PM
(This post was last modified: May-26-2018, 03:14 PM by buran.)
@ 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:;
Posts: 566
Threads: 10
Joined: Apr 2017
May-26-2018, 07:36 PM
(This post was last modified: May-26-2018, 07:36 PM by volcano63.)
(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.
Posts: 8,167
Threads: 160
Joined: Sep 2016
May-26-2018, 07:48 PM
(This post was last modified: May-26-2018, 07:48 PM by buran.)
(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'
Posts: 566
Threads: 10
Joined: Apr 2017
May-26-2018, 08:04 PM
(This post was last modified: May-26-2018, 08:04 PM by volcano63.)
As I have mentioned above, I answered the wrong question - not the one that was asked - so consider me downvoted
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
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.
Posts: 8,167
Threads: 160
Joined: Sep 2016
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???
|