Home > database >  Filtering list of objects based on attribute
Filtering list of objects based on attribute

Time:04-22

I have 4 objects.

class MyObject:
    def __init__(self, id: int, result_name: str):
        self.id = id
        self.result = Result(result_name)


class Result:
    def __init__(self, name: str):
        self.name = name

object1 = MyObject(1, 'A')
object2 = MyObject(2, 'A')
object3 = MyObject(3, 'B')
object4 = MyObject(4, 'B')

They're stored in a tuple:

x_ids = (object1, object2, object3, object4)

I want bases on parameters:

[x.result.name for x in x_ids]  
>> ("A", "A", "B", "B")

Have list of resulting list, just two objects with "A", and "B" attribute

   result = (object(1or2), object(3or4))

How can I achieve it with list comprehensions?

CodePudding user response:

You can do this very easily with a set:

class MyObject:
    def __init__(self, id_, result_name):
        self.id_ = id_
        self.result = Result(result_name)


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

object1 = MyObject(1, 'A')
object2 = MyObject(2, 'A')
object3 = MyObject(3, 'B')
object4 = MyObject(4, 'B')

T = (object1, object2, object3, object4)

S = {o.result.name for o in T}

print(S)

Output:

{'A', 'B'}

Note:

You could obviously convert the set to a list if that's what you need.

Use of id not a great idea as a variable name

CodePudding user response:

You can that using reduce from functools.

Let's start by creating the sample data:

class MyObject:
    def __init__(self, id: int, result_name: str):
        self.id = id
        self.result = Result(result_name)


class Result:
    def __init__(self, name: str):
        self.name = name

object1 = MyObject(1, 'A')
object2 = MyObject(2, 'A')
object3 = MyObject(3, 'B')
object4 = MyObject(4, 'B')

x_ids = (object1, object2, object3, object4)

Now we perform the list comprehension:

from functools import reduce
result = tuple(reduce(lambda t, s: {**t, s.result.name: s}, x_ids, {}).values())

Result:

(object2, object4)

The list comprehension (reduce) starts with an empty dict {}. Each iteration, an entry from x_ids is passed to the lambda function as s and the current state of the dict is passed as t. The dict gets updated by adding the object s with key s.result.name. If that key already exists, the entry will be overwritten - this filters out objects with the same result name. The result is a dict: {'A':object2, 'B':object4}. The result is then converted into the required tuple format.

  • Related