Select from a list of objects where a value occurs more than once
Question:
I have a list of the below custom object in python. I want to create a new list of objects where the ‘ledId’ more than once (like a list of duplicates based on an id)
The object
class CustomObject:
def __init__(self, id, ledId):
self.id = id
self.ledId = ledId
I usually use C# so I am wanting to do something like
var subList = myList.Where(obj => myList.Count(l => l.ledId == obj.ledId) > 1)
.ToList();
Is there an easy way to do this in python?
Answers:
Rewriting you code in C# to Python would be something like this:
[a for a in some_list if len([b for b in some_list if b.ledId == a.ledId]) > 1]
my_list = [
CustomObject(1, 10),
CustomObject(2, 20),
CustomObject(3, 10),
CustomObject(4, 30),
CustomObject(5, 10)
]
duplicates = [obj for obj in my_list if len(list(filter(lambda x: x.ledId == obj.ledId, my_list))) > 1]
The other solutions will work, but for the record, the algorithm as presented here is in O(n^2), since you run the count
for each iteration. You can make it O(n) by counting once, and storing the result in a dict
:
from collections import defaultdict
counts = defaultdict(int)
for custom_object in sub_list:
counts[custom_objects.ledId] += 1
result = [x for x in sub_list if counts[x.ledId] > 1]
It is also a great opportunity to use defaultdict
, but you do lose the very functional approach from C#, to make it more "Pythonic".
I have a list of the below custom object in python. I want to create a new list of objects where the ‘ledId’ more than once (like a list of duplicates based on an id)
The object
class CustomObject:
def __init__(self, id, ledId):
self.id = id
self.ledId = ledId
I usually use C# so I am wanting to do something like
var subList = myList.Where(obj => myList.Count(l => l.ledId == obj.ledId) > 1)
.ToList();
Is there an easy way to do this in python?
Rewriting you code in C# to Python would be something like this:
[a for a in some_list if len([b for b in some_list if b.ledId == a.ledId]) > 1]
my_list = [
CustomObject(1, 10),
CustomObject(2, 20),
CustomObject(3, 10),
CustomObject(4, 30),
CustomObject(5, 10)
]
duplicates = [obj for obj in my_list if len(list(filter(lambda x: x.ledId == obj.ledId, my_list))) > 1]
The other solutions will work, but for the record, the algorithm as presented here is in O(n^2), since you run the count
for each iteration. You can make it O(n) by counting once, and storing the result in a dict
:
from collections import defaultdict
counts = defaultdict(int)
for custom_object in sub_list:
counts[custom_objects.ledId] += 1
result = [x for x in sub_list if counts[x.ledId] > 1]
It is also a great opportunity to use defaultdict
, but you do lose the very functional approach from C#, to make it more "Pythonic".