Reputation: 73
I have done my research, however all these techniques return true, i need them to return false.
print set([2, 2]).issubset([2, 3, 3]) #returns True
print set([2, 3, 3]).issuperset(set([2, 2])) #returns True
print all(x in {2, 3, 3} for x in [2, 2]) #returns True
print set([2, 2]) <= set([2, 3, 3]) #returns True
The lists I'm comparing have duplicate numbers
Upvotes: 2
Views: 177
Reputation: 72
Mathematically answers by python functions are correct. It seems you also want to check the the number of elements. So, a user defined function will look like
def compare(listsuper,listsub):
stat=None
for element in listsuper:
if listsuper.count(element)==listsub.count(element):
pass
else:
stat=False
if stat==None:
for element in listsub:
if element in listsub and element in listsuper:
pass
else:
stat=False
if stat==None:
stat=True
return stat
print compare([2,3,3],[2, 2])
Hope this function works as you want
Upvotes: 0
Reputation: 15887
I'm still uncertain what you're really asking. Let's go with:
A = [2,2]
B = [2,3,3]
And the question being if you can make A by choosing without replacement out of B. That is, not only should the items in A be a subset of those in B, there must be at least as many of each in B as there are in A.
One way to test this is using collections.Counter:
from collections import Counter
countsA = Counter(A)
countsB = Counter(B)
difference = countsA - countsB # any extra items in A
print difference, not difference
Output: Counter({2: 1}) False
Since collections are true if they contain anything, we can negate it for the False
value you asked for. This difference can also be used to show exactly which items A had that couldn't be taken out of B, in this case 1 count of the item 2.
Upvotes: 2
Reputation: 15204
How about this:
a = [2, 2]
b = [2, 3, 3]
from collections import Counter as cC
fa = cC(a)
print(fa) # Counter({2: 2})
fb = cC(b)
print(fb) # Counter({3: 2, 2: 1})
test = all(fa[entry] <= fb.get(entry, -1e+30) for entry in fa)
print(test) # False
Or according to what @ChrisRand said in the comments:
test = fa - fb == {}
print(test) # False
Upvotes: 1
Reputation: 16720
You can use list.count
inside of the all
function:
all(l1.count(i) <= l2.count(i) for i in set(l1))
For every element in l1
, this will check if there is at least as many ocurences in l2
.
If any element of l1
appears fewer times in l2
, then the all
function will return False
.
The conversion of l1
into a set
prevents the number of iterations from increasing when l1
consists in a large number of the same value.
Test:
>>> f = lambda l1, l2: all(l1.count(i) <= l2.count(i) for i in set(l1))
>>> f([2, 2], [2, 3, 3])
False
>>> f([2, 2], [2, 2, 3])
True
Upvotes: 3
Reputation: 1725
Just look for an implementation of a multiset. It should pass (most of) your test cases.
Upvotes: 0