简体   繁体   中英

Group objects with an identical list attribute

I have two classes:

class A:
   def __init__(self, name, li):
      self.b_list = li

class B:
   def __init__(self, i):
      self.i = i

class A contains a list of objects of type class B .

Assuming I have a list of class A objects, how can I group the class A objects that have an identical b_list together?

For example:

a_list = []

li = [B(1), B(2), B(3)]
a_list.append(A(li))

li = [B(2), B(3)]
a_list.append(A(li))

li = [B(1), B(2), B(3)]
a_list.append(A(li))

After processing this should give us two lists, one list with the first and third A , and another list with only the second A . Or in a nutshell:

result = [
   [ A([B(1),B(2),B(3)]), A([B(1),B(2),B(3)]) ],
   [ A([B(2),B(3)] ]
]

For starters, I've removed the name parameter from class A, since the rest of your details omitted it.

To group your class A objects together, you're going to need to define exactly what is meant when two A objects are equal. I've created a __cmp__ method that will let us sort on A objects by comparing them.

Now, since your A objects are composed of B objects, you're going to need something to define what is meant by two B objects being equal. I've created a __eq__ method in class B that does that.

Next, I've sorted the A instances to make grouping them easier, and added a __str__ method to class A, and a __repr__ method to class B so you can verify that they are being grouped together correctly.

I haven't added any error checking anywhere, so this code is a little fragile.

class A:
    def __init__(self, li):
        self.b_list = li

    def __cmp__(self, other):
        return cmp([elem.i for elem in self.b_list], 
                   [elem.i for elem in other.b_list])

    def __str__(self):
        return "A({})".format(self.b_list)

class B:
    def __init__(self, i):
       self.i = i

    def __eq__(self, other):
       return self.i == other.i

    def __repr__(self):
        return "B({})".format(self.i)

def main():

    a_list = []

    li = [B(1), B(2), B(3)]
    a_list.append(A(li))

    li = [B(2), B(3)]
    a_list.append(A(li))

    li = [B(1), B(2), B(3)]
    a_list.append(A(li))

    result = []
    last_item = None
    for item in sorted(a_list):
        if last_item and item == last_item:
            result[-1] = result[-1] + [item]
        else:
            result.append([item])
        last_item = item

    for row in result:
        print [str(elem) for elem in row]

if __name__ == '__main__':
    main()

Result:

['A([B(1), B(2), B(3)])', 'A([B(1), B(2), B(3)])']
['A([B(2), B(3)])']

You can sort a_list using the attribute b_list as a key.

a_list.sort(key=lambda a:a.b_list)

or:

from operator import itemgetter

a_list.sort(key=itemgetter("b_list"))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM