问题
I have a list of instances from the same class, and I want to make my list distinct based on a property in the class. What is the most pythonic way to achieve this?
Here is some sample code:
#!/usr/bin/python
#-*- coding:utf-8 -*-
class MyClass(object):
def __init__(self, classId, tag):
self.classId = classId
self.tag = tag
myList = []
myInstance1 = MyClass(1, "ABC")
myInstance2 = MyClass(2, "DEF")
myInstance3 = MyClass(3, "DEF")
myList.append(myInstance1)
myList.append(myInstance3) # note that the order is changed deliberately
myList.append(myInstance2)
If I want to sort my list now based on one of the properties in MyClass, I usually just sort it by key, and set the key using a lambda expression - like this:
myList.sort(key=lambda x: x.classId)
for x in myList:
print x.classId
$ python ./test.py
1
2
3
Is it possible to use a similar method (lambda, map or similar) to make the list distinct based on the "tag" property? Also, if this is possible, is it the most "pythonic" way to make a list distinct based on a property of a class in that list?
I have already tried searching both SO and Google for topics on this matter, but all the results I found dealt with simple lists that only contained a numeric value and not a custom object..
回答1:
You can use python dict comprehension
{x.tag: x for x in myList}.values()
For your example:
>>> class MyClass(object):
... def __init__(self, classId, tag):
... self.classId = classId
... self.tag = tag
...
>>> myList = [MyClass(1, "ABC"), MyClass(2, "DEF"), MyClass(3, "DEF")]
>>> uniqList = {x.tag: x for x in myList}.values()
>>> print [x.classId for x in uniqList]
[1, 3]
回答2:
Assuming the property you wish to key on is immutable, you can use a dict:
d = {}
for x in xs:
d[x.tag] = x
Now d
will contain a single x
per tag
value; you can use d.values()
or d.itervalues()
to get at the xs
.
NB. here last matching item wins; to have the first one win, iterate in reverse.
来源:https://stackoverflow.com/questions/16898977/how-to-make-a-list-in-python-distinct-based-on-a-property-of-the-class-in-the-li