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:
- count the objects in list1 using a dictionary, call that counts1
- count the objects in list2 using a dictionary, call that counts2
- subtract counts in count2 from the counts in count1 of matching keys
- 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))