1

I have two Dictionaries resources, and available_resources:

resources = {'B': 1, 's': 2, 't': 3, 'e': 3, '!': 1, 'h': 1, 'i': 1, ' ': 3, 'o': 1, 'g': 1, 'E': 1, 'A': 1, 'x': 2, 'p': 1, 'l': 1, 'r': 1}


available_resources = {'A': 1, 'l': 1, 'g': 1, 'o': 1, 'E': 1, 'x': 1, 'p': 1, 'e': 3, 'r': 1, 't': 3, ' ': 3, 'i': 1, 's': 2, 'h': 1, 'B': 1, '!': 1}

I want to check if resources is a subset of available_resources (if each element contained in the dictionary is <= the corresponding value entry in the resources dictionary)

I've tried:

    if all(available_resources.get(key, None) == val for key, val
                             in resources.items()):
          return True

It is returning false, is there another way I can get it to work?

  • 1
    protip: constructs like `if (condition): return True` almost always should be `return (condition)` – Marat Oct 20 '21 at 15:31
  • 3
    The question is worded in a confusing way. You talk about the *subset* relation (and your code seems to be trying to test that) but other parts suggest that it is a different relation that you are trying to test -- that of corresponding values being `<=`. Please clarify. – John Coleman Oct 20 '21 at 15:31
  • @JohnColeman My guess is that the dicts represent multisets, and the OP is talking about the "subset relation" for multisets. (Although I would also appreciate if the question was more clear!) – Stef Oct 20 '21 at 15:40

5 Answers5

2

Could it be a simple sign error? From "==" val to "<=" val? I got true from the below.

if all(available_resources.get(key, None) <= val for key, val
                             in resources.items()):
    return True
NanoBit
  • 196
  • 1
  • 10
  • 1
    Shouldn't that be `>=`? (The wording of the question isn't clear, so perhaps OP is confused on the issue). – John Coleman Oct 20 '21 at 15:27
  • @JohnColeman yes, you could be correct there! Currently, the question is a bit unclear. For example, what if an element exists in one but not the other. I hope the author can update with more details. – NanoBit Oct 20 '21 at 16:26
1

If all the values are integers, one approach is to use collections.Counter:

from collections import Counter

resources = {'B': 1, 's': 2, 't': 3, 'e': 3, '!': 1, 'h': 1, 'i': 1, ' ': 3, 'o': 1, 'g': 1, 'E': 1, 'A': 1, 'x': 2, 'p': 1, 'l': 1, 'r': 1}
available_resources = {'A': 1, 'l': 1, 'g': 1, 'o': 1, 'E': 1, 'x': 1, 'p': 1, 'e': 3, 'r': 1, 't': 3, ' ': 3, 'i': 1, 's': 2, 'h': 1, 'B': 1, '!': 1}


res = bool(Counter(resources) - Counter(available_resources))
print(res)

Output

True
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76
  • 1
    New in version 3.10: you can compare Counter objects directly with `a <= b` rather than using `bool(b - a)`. *"Counters support rich comparison operators for equality, subset, and superset relationships: ==, !=, <, <=, >, >=. All of those tests treat missing elements as having zero counts so that Counter(a=1) == Counter(a=1, b=0) returns true. New in version 3.10: Rich comparison operations we were added "* – Stef Oct 20 '21 at 15:42
  • 1
    @Stef It seems at the end I was right: https://twitter.com/mesejo410/status/1201845851255123968?s=20 – Dani Mesejo Oct 20 '21 at 15:47
1

You can use the <= operator from sets. This operator determines whether one set is a subset of the other.

As follows:

>>> resources.items() <= available_resources.items()
False

This returns False as there is a difference between the element x in the different dict. You can see this difference using the set operator ^ with will return you the symmetric difference between the dict:

>>> resources.items() ^ available_resources.items()
{('x', 1), ('x', 2)}
Antoine Dubuis
  • 4,974
  • 1
  • 15
  • 29
0

You need to use <= instead of ==

>>> all(available_resources.get(k, -1)<=v for k,v in resources.items())
True

Also, above method may fail if resources contains some key that doesn't exist in available_resources, and you can additionally check if the keys in resources are subset of the keys in available_resources for this condition

>>> all(available_resources.get(k, -1)<=v for k,v in resources.items()) and\
        set(resources).issubset(available_resources)
True
ThePyGuy
  • 17,779
  • 5
  • 18
  • 45
0

I have tested the answers in this stackoverflow question: click here

And i think it's works for you!

all(item in available_resources.items() for item in resources.items())

# - or - # 

available_resources.items() <= resources.items()