How can I find the closest, positive value, from a dictionary's item's keys? (Python)

Question:

Assuming I have a dictionary in this structure:

data = {
    '111': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 301},
    '112': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 302},
    '113': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 377},
    '114': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 311},
    '115': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 314},
    '116': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 306},
    '117': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 387}
    #...
}

Based on ‘c’ key, I’m looking for a way to return a dict item from which, a given input (e.g ‘312’), is the closest positive value in that key.

E.g:

input = 312

expected result:

>>> {'115': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 314}}

The script would ignore negative values (for example, item ‘114’ ‘c’ key is 311, which is closer to 312, but ignored since it’s less than the input number).

I’ve tried looking on google for ways to do this, but the only results I got were examples for the closest positive or negative, while the value I’m looking for has to be positive.

Asked By: Hugo Rieth

||

Answers:

You can use a generator expression to filter the keys with a c that is below the target and min to find the closet key:

target = 312

closest_key_above = min((k for k, d in data.items() if d['c']>target),
                        key=lambda k: data[k]['c']-target)

Output:

'115'

To get the dictionary:

{closest_key_above: data[closest_key_above]}
# {'115': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 314}}

as a function

def find_closest(data, target):
    key = min((k for k, d in data.items() if d['c']>target),
              key=lambda k: data[k]['c']-target)
    return {key: data[key]}

find_closest(data, 307)
# {'114': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 311}}
Answered By: mozway
[ins] In [19]: data = {
          ...:     '111': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 301},
          ...:     '112': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 302},
          ...:     '113': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 377},
          ...:     '114': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 311},
          ...:     '115': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 314},
          ...:     '116': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 306},
          ...:     '117': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 387},
          ...:  }

[ins] In [20]: def closest_positive(inp, data):
          ...:     data = {k: v for k, v in data.items() if v['c'] >= inp}
          ...:     min_key = min(data, key = lambda k: data[k]['c'] - inp)
          ...:     return {min_key: data[min_key]}
          ...:

[ins] In [21]: closest_positive(312, data)
Out[21]: {'115': {'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 314}}

The first line of the func drop all dict entries with the c field smaller than the sought one.

The second once finds the "minimal" key in the rest of the dict by using a custom comparison function (the key = lambda ... argument of min()).

Answered By: Grisha

Code:

INPUT = int(input("Enter value:"))` #Get input

#count the difference between input and each c of dictionary
#mind not allowing smaller values to comes for calculation, lastly gettng min of list

nearst = min([data[d]['c'] for d in data if data[d]['c']>=INPUT], key=lambda x: x-INPUT)

#now loop over dictionary of that min in c select that values

[data[d] for d in data if data[d]['c']==nearst]

Output:

[{'a': 'xxxxxx', 'b': 'xxxxxx', 'c': 314}]
Answered By: R. Baraiya
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.