-3

I am looking to create a function that will check if multiple keys are present in a dictionary and return a value that indicates which keys were present. I know I could write something like:

def param_checker(parameters):
    if 'foo' in parameters:
        if 'bar' in parameters:
            if 'qux' in parameters:
                return 0
            else:
                return 1
        elif 'baz' in parameters:
            if 'qux' in parameters:
                return 2
            else:
                return 3
        else:
            return 4
    elif 'quxx' in parameters:
        if 'bar' in parameters:
            return 5
        elif 'qux' in parameters:
            if 'baz' in parameters:
                return 6
            else:
                return 7
        else:
            return 8
    else:
        return 9

However, the above example is both messy and clunky. The complexity also scales with the number of parameters you need to check to return a value. For example, I needed 3 layers of if conditions to check the keys foo, bar, and qux. I know I could chain the if conditions inline, but it is still messy and clunky.

This is somewhat similar to Python check if list of keys exist in dictionary. The big difference here is that instead of checking if they all exist or not, I am looking to return a value indicating what combination of keys exist.

Note: I did not write out all possible combinations in the provided sample code, as that would be tedious when I am just trying to illustrate the problem.

Below is a example of invoking the function to check which keys are present.

d = dict()
d['foo'] = 'blah'
d['bar'] = 'blah'

val = param_checker(d)
# val represents a unique value indicating which keys are present in dictionary d

I will know ahead of time what keys could be in the dictionary, so I can have some sort of list of possible keys, like:

keys = ["foo", "bar", "baz", "qux", "quxx"]

I am hoping to build a function that can check N keys and return a unique value indicating which ones where present. How can I efficiently do this?

Andrew
  • 902
  • 1
  • 11
  • 28
  • Please post a sample of your input and your desired output. – Ajax1234 Nov 06 '17 at 22:14
  • [Minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) applies here. We cannot effectively help you until you post your MCVE code and accurately describe the problem. We should be able to paste your posted code into a text file and reproduce the problem you described. The posted code merely defines a function and quits. – Prune Nov 06 '17 at 22:15
  • Why are you hard coding the values? Is it just for sample here or is that actually what you are using? – theBrainyGeek Nov 06 '17 at 22:16
  • This isn't just an implementation problem. The semantics of this function are also extremely confusing. Why do some values not matter when certain other values are found? Why 5 and not 6 for some particular case? What's the meaning of all this? – user2357112 Nov 06 '17 at 22:18
  • Suppose we can easily find the subset of a set of keys `["foo", "bar", "qux", "baz", "quxx"]` that is in a dictionary (we can) ... that what is your rule for mapping that subset to a number? – donkopotamus Nov 06 '17 at 22:19
  • @user2357112 I did not go through all possible combinations of keys `["foo", "bar", "qux", "baz", "quxx"]`. Also, the value `5` or `6` is just some unique value that can be used to indicate which combination of keys was present in `parameters` – Andrew Nov 06 '17 at 22:34
  • @donkopotamus I am looking for a unique return value. In this sample code, each number is for a unique combination. The sample code is also just to illustrate the problem pace. If the unique return values is a number or a hash or something else, that can also work. It just need to uniquely identify the combination of keys that were present. – Andrew Nov 06 '17 at 22:36
  • @theBrainyGeek This is just sample code to illustrate the problem. I would not want to hard code values in a structure like this in the full function checking `N` keys. That would be a nightmare. – Andrew Nov 06 '17 at 22:38
  • @Ajax1234 added some sample code illustrates a sample usage scenario. – Andrew Nov 06 '17 at 22:51

4 Answers4

1
keyseq = ('foo', 'bar', 'quux')
keymap = {key: 1 << e for (e, key) in enumerate(keyseq)}
return sum(keymap[key] for key in keymap if key in D)
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
0

Something like this (assuming Python 3)?

from itertools import compress

queries = ["a", "b", "c", "d"]
in_dict = [q in d for q in queries]
existing_keys = compress(queries, in_dict)

You can of course wrap this in a function where queries become the input parameter and d is the input dictionary.

bow
  • 2,503
  • 4
  • 22
  • 26
0

Make a set of your desired keys. Make a set of the dict's keys. Take the intersection. Count.

master = {
    "foo": 1,
    "bar": 5,
    "qux": 18,
    "lemon": -6,
    "quxx": "How boring are examples?",
    "dog": False
}

tag = {
    "foo", "bar", "baz", "qux", "quxx"
}

master_set = set(master.keys())
found =  master_set.intersection(tag)

print (len(found), found)

Output:

4 {'quxx', 'foo', 'qux', 'bar'}
Prune
  • 76,765
  • 14
  • 60
  • 81
0

You can try this:

keys = ["foo", "bar", "baz", "qux", "quxx"]
counter = {i:d.keys().count(i) for i in keys}
Ajax1234
  • 69,937
  • 8
  • 61
  • 102