Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Check if Python List Contains Elements of Another List Duplicates Not Ignored

I'm trying to check if a small list contains all the numbers that exist in another bigger list Case 1 :- list1 : [97,97,196] list 2 : [97,97,101,103,196]

  • This should return True because all elements in list1 are already in list2

Case 2 :- list1 :[97,97,196] list 2 : [97,101,103,196]

  • This should return False because list1 has two 97's while list2 only contains one 97
list1 = [97,97,196]
list2 = [97,97,99,101,103,196]


def isConsist(list1,list2):
    check = False

    # Iterate in the 1st list
    for m in list1:

        # Iterate in the 2nd list
        for n in list2:

            # if there is a match
            if m == n:
                check = True
                list2.remove(n) // remove the found element 
            else:
                check = False
                return False
    return check

check = isConsist(list1,list2)
print(check)


This is my code but it is not working correctly

My code got my false because when it comes to check the 196 in the first list it comapares it to 99 in the second list and then it returns False

like image 956
Mustafa Adel Avatar asked Sep 01 '25 20:09

Mustafa Adel


2 Answers

Use a collections.Counter object, which can be used like a multiset. Essentially, you are asking if the multiset created by list1 is empty after taking the difference with the multiset of list 2. So consider:

>>> from collections import Counter
>>> list1 = [97,97,196]
>>> list2 = [97,97,101,103,196]
>>> Counter(list1) - Counter(list2)
Counter()

But if we do:

>>> list2 = [97,101,103,196]
>>> Counter(list1) - Counter(list2)
Counter({97: 1})

Note, the above will be linear time and space.

Another way to think about this from a high level:

  1. count the objects in list1 using a dictionary, call that counts1
  2. count the objects in list2 using a dictionary, call that counts2
  3. subtract counts in count2 from the counts in count1 of matching keys
  4. the result is true if all the counts are 0 or negative, false otherwise.

Wrapping it all up, your function can therefore be written as:

from collections import Counter

def is_consistent(list1, list2):
    return bool(Counter(list1) - Counter(list2))

EDIT:

Just discovered this, but since Python 3.10, collections.Counter class now support rich comparison operators for multiset equality, subset, and superset relationships!

So you can actually use:

def is_consistent(list1, list2):
    return Counter(list1) <= Counter(list2)

Note, you could do this "by hand" with a regular dictionary, if only for illumination purposes:

def _count(lst):
    counts = {}
    for item in lst:
        counts[item] = counts.get(item, 0) + 1
    return counts

def is_consistent(list1, list2):
    counts1 = _count(list1)
    counts2 = _count(list2)
    for k in counts1:
        counts1[k] -= counts2.get(k, 0)
    for v in counts1.values():
        if v > 0:
            return False
    return True

Now, you were close with your approach (albeit, it is inefficient, quadratic time and linear space) if as you pointed out, you don't return early. Here is what I think you were trying to get at:

def is_consistent(list1, list2):
    list1_copy = list1.copy()
    for item in list2:
        if item in list1:
            try:
                list1_copy.remove(item)
            except ValueError:
                pass
    return bool(list1_copy)

Note, bool(list1_copy) is equivalent to len(list1_copy) == 0

like image 79
juanpa.arrivillaga Avatar answered Sep 03 '25 10:09

juanpa.arrivillaga


Converting a list into set will not solve your problem. The best way is to use collections.Counter. Here is my code:

from collections import Counter

list1 = [97, 97, 196]
list2 = [97, 97, 99, 101, 103, 196]


def consist(a, b):
    a_count = Counter(a)
    b_count = Counter(b)
    for key in a_count:
        if key not in b_count:
            return False
        if b_count[key] > a_count[key] or a_count[key] > b_count[key]:
            return False
    return True


print(consist(list1, list2))

Here, in first if condition, we are checking if element from list1 is present in list2 or not. In second if condition, we are checking if count of element in list1 is same as count of element in list2 or not.

This is the best answer I've got. Hope it helps.. :)

like image 36
Nilesh Bhave Avatar answered Sep 03 '25 10:09

Nilesh Bhave