Jacob Lee
Jacob Lee

Reputation: 73

Check if ALL elements of list A within list B

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

Answers (5)

Subrata Sarkar
Subrata Sarkar

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

Yann Vernier
Yann Vernier

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

Ma0
Ma0

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

Right leg
Right leg

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

carrdelling
carrdelling

Reputation: 1725

Just look for an implementation of a multiset. It should pass (most of) your test cases.

Upvotes: 0

Related Questions