How to efficiently compare two unordered lists (not sets) in Python?

前端 未结 10 1107
刺人心
刺人心 2020-11-22 15:00
a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]

a & b should be considered equal, because they have exactly the same elements, only in different

相关标签:
10条回答
  • 2020-11-22 15:32

    I hope the below piece of code might work in your case :-

    if ((len(a) == len(b)) and
       (all(i in a for i in b))):
        print 'True'
    else:
        print 'False'
    

    This will ensure that all the elements in both the lists a & b are same, regardless of whether they are in same order or not.

    For better understanding, refer to my answer in this question

    0 讨论(0)
  • 2020-11-22 15:33

    Let a,b lists

    def ass_equal(a,b):
    try:
        map(lambda x: a.pop(a.index(x)), b) # try to remove all the elements of b from a, on fail, throw exception
        if len(a) == 0: # if a is empty, means that b has removed them all
            return True 
    except:
        return False # b failed to remove some items from a
    

    No need to make them hashable or sort them.

    0 讨论(0)
  • 2020-11-22 15:38

    The best way to do this is by sorting the lists and comparing them. (Using Counter won't work with objects that aren't hashable.) This is straightforward for integers:

    sorted(a) == sorted(b)
    

    It gets a little trickier with arbitrary objects. If you care about object identity, i.e., whether the same objects are in both lists, you can use the id() function as the sort key.

    sorted(a, key=id) == sorted(b, key==id)
    

    (In Python 2.x you don't actually need the key= parameter, because you can compare any object to any object. The ordering is arbitrary but stable, so it works fine for this purpose; it doesn't matter what order the objects are in, only that the ordering is the same for both lists. In Python 3, though, comparing objects of different types is disallowed in many circumstances -- for example, you can't compare strings to integers -- so if you will have objects of various types, best to explicitly use the object's ID.)

    If you want to compare the objects in the list by value, on the other hand, first you need to define what "value" means for the objects. Then you will need some way to provide that as a key (and for Python 3, as a consistent type). One potential way that would work for a lot of arbitrary objects is to sort by their repr(). Of course, this could waste a lot of extra time and memory building repr() strings for large lists and so on.

    sorted(a, key=repr) == sorted(b, key==repr)
    

    If the objects are all your own types, you can define __lt__() on them so that the object knows how to compare itself to others. Then you can just sort them and not worry about the key= parameter. Of course you could also define __hash__() and use Counter, which will be faster.

    0 讨论(0)
  • 2020-11-22 15:39

    If the list contains items that are not hashable (such as a list of objects) you might be able to use the Counter Class and the id() function such as:

    from collections import Counter
    ...
    if Counter(map(id,a)) == Counter(map(id,b)):
        print("Lists a and b contain the same objects")
    
    0 讨论(0)
  • 2020-11-22 15:42

    If you have to do this in tests: https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual

    assertCountEqual(first, second, msg=None)

    Test that sequence first contains the same elements as second, regardless of their order. When they don’t, an error message listing the differences between the sequences will be generated.

    Duplicate elements are not ignored when comparing first and second. It verifies whether each element has the same count in both sequences. Equivalent to: assertEqual(Counter(list(first)), Counter(list(second))) but works with sequences of unhashable objects as well.

    New in version 3.2.

    or in 2.7: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual

    Outside of tests I would recommend the Counter method.

    0 讨论(0)
  • 2020-11-22 15:42

    If the comparison is to be performed in a testing context, use assertCountEqual(a, b) (py>=3.2) and assertItemsEqual(a, b) (2.7<=py<3.2).

    Works on sequences of unhashable objects too.

    0 讨论(0)
提交回复
热议问题