Kevin Sheahan
Kevin Sheahan

Reputation: 141

Python: removing objects form lists based on object attribute

I have a list of python objects and I'd like to remove duplicates in the list based on the time value. For example:

class MyClass(object):

    identifier = models.CharField(max_length=128)
    label = models.CharField(max_length=128)
    stat_time = models.DateTimeField(auto_now_add=True)
    def __unicode__(self):
        return str(self.label)

My list may have several instances of MyClass with the same label but different stat_times. I'd like to trim the list and have only one instance of the label with the latest stat_time.

>>> my_list
[MyClass: xxx, MyClass: yyy, MyClass: yyy, MyClass: zzz]

I'd like to end up with:

>>> my_list
[MyClass: xxx, MyClass: yyy, MyClass: zzz]

Here my_list should only contain one instance of MyClass with the 'yyy' label with the latest stat_time.

I hope I have made that clear. Any suggestions much appreciated.

Upvotes: 1

Views: 2970

Answers (2)

Steinar Lima
Steinar Lima

Reputation: 7821

I'm not sure if you should filter your object based on __unicode__(), but here is how I would have done it.

unique_objs = []

for o in my_list:
    if (o.__unicode__(), o.stat_time) in unique_objs:
        continue
    new_list.append(o)
    unique_objs.append(tuple(o.__unicode__(), o.stat_time))

Upvotes: 0

SimonT
SimonT

Reputation: 2359

One way you could do it is to create a dict mapping values of label to MyClass instances. You would add each the elements of your list to this dict, but only keep the wanted values.

aDict = dict()
for element in myList:
    s = element.label
    if s not in aDict: # the key is not used yet
        aDict[s] = element
    else:
        aDict[s] = max(aDict[s], element, key = lambda x: x.stat_time)
myList = list(aDict.items()) # iteritems() in Python 2

The lambda expression passed into max tells Python which value to compare when computing the max.

Upvotes: 1

Related Questions