Home > front end >  How to Check if Python List Contains Elements of Another List Duplicates Not Ignored
How to Check if Python List Contains Elements of Another List Duplicates Not Ignored

Time:04-06

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

CodePudding user response:

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

CodePudding user response:

Heyy!! This is my solution: First thing first, let's check if the first list is a sublist of the second one, because if not it does not have any sense to go on. Then what I'm doing is to iterate only in the first list and check if there is exactly n-occourences of that number in both of lists, if this is False, return False, else if everything is fine Return True

def isConsist(list1, list2):

# check if all the element in list1 are in list2
x = set(list1)
y = set(list2)
if not x.issubset(y):
    return False

# Iterate in the 1st list
for n1 in range(len(list1)):

    if list1.count(list1[n1]) != list2.count((list1[n1])):
        return False

return True

print(isConsist(list1, list2))

CodePudding user response:

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]:
            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.. :)

CodePudding user response:

You may try something like this

list1 = [97,97,196] 
list2 = [97,101,103,196]
[list1.remove(i) for i in list2 if i in list1]
print(bool(list1))
  • Related