How to create a lookup table with noise in Python? - python

Say I have a dictionary in Python {1:'a', 100:'b', 1024:'c'}
I want to build a function that can look for not only the exact value of the key, but also approximated values. For instance, the function can return b if the input is 99 or 101.
Could you suggest me some approaches?

If you want to keep the speed advantage of a dict, you could bin your keys, e.g. by rounding them to the nearest multiple of 10:
>>> data = {1:'a', 100:'b', 1024:'c'}
>>> fuzzy = { ((k + 5) // 10) * 10:v for k,v in data.items() }
>>> fuzzy
{0: 'a', 100: 'b', 1020: 'c'}
When you want to check if a values is close to a key in data, you simply apply the same transformation:
>>> fuzzy.get(((98+5)//10)*10)
'b'
>>> fuzzy.get(((97+5)//10)*10)
'b'
>>> fuzzy.get(((100+5)//10)*10)
'b'
>>> fuzzy.get(((101+5)//10)*10)
'b'
>>> fuzzy.get(((1022+5)//10)*10)
'c'

If you have a finite range for the values of the keys that is known in advance something like this indexing with tuples
>>> d={(0,2):'a', (99,101):'b', (1023,1025):'c'}
To find the value of a key:
Find 1024.01:
>>> d={(0,2):'a', (99,101):'b', (1023,1025):'c'}
>>> next(v for (k,v) in d.iteritems() if k[0]<=1024.01<=k[1])
'c'
Find 1025.01:
>>> next(v for (k,v) in d.iteritems() if k[0]<=1025.01<=k[1])
# throws an error because key is not found

You can make your own lookup function as follows:
import sys
def lookup(value, dict):
nearest = sys.maxint
result = ""
for k,v in dict.iteritems():
if abs(value - k) < nearest:
nearest = abs(value - k)
result = v
return result
print lookup(101, {1:'a', 100:'b', 1024:'c'})

You can search for values within 2% range (configurable) with something like this:
data = {1:'a', 100:'b', 1024:'c'}
def get_approx(data, key):
return [elem[1] for elem in data.iteritems() if elem[0]*0.98 <= key <= elem[0]*1.02]
get_approx(data, 99) # outputs ['b']

Related

python 3 dictionary key to a string and value to another string

if there is a dictionary:
dict={'a':'b'}
in python 3, i would like to convert this dictionary key to a string and its value to another string:
print(key)
key='a'
print(type(key))
str
print(value)
value='a'
print(type(value))
str
Some attempts:
str(dict.key()) # returns 'dict' object has no attribute 'key'
json.dump(dict) # returns {'a':'b'} in string, but hard to process
Any easy solution? Thank you!
Use dict.items():
You can use dict.items() (dict.iteritems() for python 2), it returns pairs of keys and values, and you can simply pick its first.
>>> d = { 'a': 'b' }
>>> key, value = list(d.items())[0]
>>> key
'a'
>>> value
'b'
I converted d.items() to a list, and picked its 0 index, you can also convert it into an iterator, and pick its first using next:
>>> key, value = next(iter(d.items()))
>>> key
'a'
>>> value
'b'
Use dict.keys() and dict.values():
You can also use dict.keys() to retrieve all of the dictionary keys, and pick its first key. And use dict.values() to retrieve all of the dictionary values:
>>> key = list(d.keys())[0]
>>> key
'a'
>>> value = list(d.values())[0]
>>> value
'b'
Here, you can use next(iter(...)) too:
>>> key = next(iter(d.keys()))
>>> key
'a'
>>> value = next(iter(d.values()))
'b'
Ensure getting a str:
The above methods don't ensure retrieving a string, they'll return whatever is the actual type of the key, and value. You can explicitly convert them to str:
>>> d = {'some_key': 1}
>>> key, value = next((str(k), str(v)) for k, v in d.items())
>>> key
'some_key'
>>> value
'1'
>>> type(key)
<class 'str'>
>>> type(value)
<class 'str'>
Now, both key, and value are str. Although actual value in dict was an int.
Disclaimer: These methods will pick first key, value pair of dictionary if it has multiple key value pairs, and simply ignore others. And it will NOT work if the dictionary is empty. If you need a solution which simply fails if there are multiple values in the dictionary, #SylvainLeroux's answer is the one you should look for.
To have a solution with several keys in dict without any import I used the following light solution.
dict={'a':'b','c':'d'}
keys = "".join(list(dict.keys()))
values = "".join(list(dict.values()))
>>> d = { 'a': 'b' }
>>> d.items()
dict_items([('a', 'b')])
At this point, you can use a destructuring assignement to get your values:
>>> [[key, value]] = d.items()
>>> key
'a'
>>> value
'b'
One advantage in this solution is it will fail in case of d containing several entries, instead of silently ignoring the issue.
>>> d = { 'a': 'b', 'c':'d' }
>>> [[key, value]] = d.items()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 1)
Finally, if you need to ensure key and value to be strings, you may add a list comprehension:
>>> d = { 1: 2 }
>>> [[key, value]] = ((str(key), str(value)) for key,value in d.items())
>>> key
'1'
>>> value
'2'
Make lists of keys and values:
dict={'a':'b'}
keys = list(dict.keys())
values = list(dict.values())
then make variables:
key = keys[0]
value = values[0]
https://docs.python.org/3/library/stdtypes.html#typesmapping
The methods are you looking for are keys() and values().

Adding nonzero items from a dictionary to another dictionary

I have a set of reactions (keys) with values (0.0 or 100) stored in mydict.
Now I want to place non zero values in a new dictionary (nonzerodict).
def nonzero(cmod):
mydict = cmod.getReactionValues()
nonzerodict = {}
for key in mydict:
if mydict.values() != float(0):
nonzerodict[nz] = mydict.values
print nz
Unfortunately this is not working.
My questions:
Am I iterating over a dictionary correctly?
Am I adding items to the new dictionary correctly?
You are testing if the list of values is not equal to float(0). Test each value instead, using the key to retrieve it:
if mydict[key] != 0:
nonzerodict[key] = mydict[key]
You are iterating over the keys correctly, but you could also iterate over the key-value pairs:
for key, value in mydict.iteritems():
if value != 0:
nonzerodict[key] = value
Note that with floating point values, chances are you'll have very small values, close to zero, that you may want to filter out too. If so, test if the value is close to zero instead:
if abs(value) > 1e-9:
You can do the whole thing in a single dictionary expression:
def nonzero(cmod):
return {k: v for k, v in cmod.getReactionValues().iteritems() if abs(v) > 1e-9}
Its simple and you can it by below way -
>>> d = {'a':4,'b':2, 'c':0}
>>> dict((k,v) for k,v in d.iteritems() if v!=0)
{'a': 4, 'b': 2}
>>>
Replace if condition in you code with:
if mydict[key]:
nonzerodict[key] = mydict[key]
Your solution can be further simplified as:
def nonzero(cmod):
mydict = cmod.getReactionValues()
nonzerodict = {key: value for key, value in mydict.iteritems() if value}

Remove the smallest element(s) from a dictionary

I have a function such that there is a dictionary as parameters, with the value associated to be an integer. I'm trying to remove the minimum element(s) and return a set of the remaining keys.
I am programming in python. I cant seem to remove key value pairs with the same key or values. My code does not work for the 2nd and 3rd example
This is how it would work:
remaining({A: 1, B: 2, C: 2})
{B, C}
remaining({B: 2, C : 2})
{}
remaining({A: 1, B: 1, C: 1, D: 4})
{D}
This is what I have:
def remaining(d : {str:int}) -> {str}:
Remaining = set(d)
Remaining.remove(min(d, key=d.get))
return Remaining
One approach is to take the minimum value, then build a list of keys that are equal to it and utilise dict.viewkeys() which has set-like behaviour and remove the keys matching the minimum value from it.
d = {'A': 1, 'B': 1, 'C': 1, 'D': 4}
# Use .values() and .keys() and .items() for Python 3.x
min_val = min(d.itervalues())
remaining = d.viewkeys() - (k for k, v in d.iteritems() if v == min_val)
# set(['D'])
On a side note, I find it odd that {B: 2, C : 2} should be {} as there's not actually anything greater for those to be the minimum as it were.
That's because you're trying to map values to keys and map allows different keys to have the same values but not the other way! you should implement a map "reversal" as described here, remove the minimum key, and then reverse the map back to its original form.
from collections import defaultdict
# your example
l = {'A': 1, 'B': 1, 'C': 1, 'D': 4}
# reverse the dict
d1 = {}
for k, v in l.iteritems():
d1[v] = d1.get(v, []) + [k]
# remove the min element
del d1[min(d1, key=d1.get)]
#recover the rest to the original dict minus the min
res = {}
for k, v in d1.iteritems():
for e in v:
res[e] = k
print res
Comment:
#Jon Clements's solution is more elegant and should be accepted as the answer
Take the minimum value and construct a set with all the keys which are not associated to that value:
def remaining(d):
m = min(d.values())
return {k for k,v in d.items() if v != m}
If you don't like set comprehensions that's the same as:
def remaining(d):
m = min(d.values())
s = set()
for k,v in d.items():
if v != m:
s.add(k)
return s
This removes all the items with the minimum value.
import copy
def remaining(dic):
minimum = min([i for i in dic.values()])
for k, v in copy.copy(dic.items()):
if v == minimum: dic.pop(k)
return set(dic.keys())
An easier way would be to use pd.Series.idxmin() or pd.Series.min(). These functions allow you to find the index of the minimum value or the minimum value in a series, plus pandas allows you to create a named index.
import pandas as pd
import numpy as np
A = pd.Series(np.full(shape=5,fill_value=0))#create series of 0
A = A.reindex(['a','b','c','d','e'])#set index, similar to dictionary names
A['a'] = 2
print(A.max())
#output 2.0
print(A.idxmax())#you can also pop by index without changing other indices
#output a

Dictionary help for Python

I have a dictionary, and I want to iterate over the keys, test the keys, and then print the keys that pass the test.
For example, my code looks like this at the moment:
x = {4:"a", 1:"b", 0:"c", 9:"d"}
for t in x:
if t > 2:
print t
However, all the output is, is just the key.
How do I get the code to print out the value at the end of the code, instead of the key?
Also, how do I get this in the form of a dictionary, {key : value}?
You could try this: print t, x[t]
Or this:
for key, val in x.items():
if key > 2:
print key, val
If you want to get only the pairs that you're printing into a new dictionary, then you have to put them there:
newdict = {}
for key, val in x.items():
if key > 2:
print key, val
# put all the keys > 2 into the new dict
newdict[key] = val
Of course that solution is printing when it inserts. If you're doing more than just a little script you will get more utility out of breaking functionality out, making sure that any given function does one, and only one, thing:
def filter_dict(x):
newdict = {}
for key, val in x.items():
if key > 2:
# put all the keys > 2 into the new dict
newdict[key] = val
def pretty_print(dct):
for k, v in dct.items():
print k, v
filtered = filter_dict(x)
pretty_print(dct)
This doesn't apply if you're just debugging, of course, and there are ways in which it depends on how large of a program you're writing: if you're doing a simple enough thing then the extra flexibility you get by breaking functionality up is lost because of the extra effort of figuring out exactly what any given thing does. That said: you should generally do it.
Additionally, the most idiomatic way to filter lists on a simple comparison in Python is to use a dict comprehension (new in Python 2.7/3.0):
filtered = {key: val for key, val in x if key > 2}
print [(k,v) for k,v in yourDict.items() if test(k)]
(You could just do k for k,v in... or v for k,v in.... If you only need values, you can use yourDict.values().)
x = {4:"a", 1:"b", 0:"c", 9:"d"}
for t in x:
if t > 2:
print '{}: {}'.format(t, x[t])
Slightly more pythonic:
>>> for key, value in x.iteritems():
... if key > 2:
... print '{}: {}'.format(key, value)
...
4: a
9: d
edit: To just print the value:
>>> for key, value in x.iteritems():
... if key > 2:
... print value
...
a
d
key as well as value:
x = {4:"a", 1:"b", 0:"c", 9:"d"}
for k,v in x.items():
if k>2: print"{%d : %s}"%(k,repr(v))
{4 : 'a'}
{9 : 'd'}
just value:
x = {4:"a", 1:"b", 0:"c", 9:"d"}
for k,v in x.items():
if k>2:print v
a
d
Just the keys:
>>> [k for k in x.iterkeys() if k > 2]
[4, 9]
Just the values:
>>> [v for k,v in x.iteritems() if k > 2]
['a', 'd']
Key-value pairs:
>>> [(k, v) for k,v in x.iteritems() if k > 2]
[(4, 'a'), (9, 'd')]
As a dict:
>>> dict((k,v) for k,v in x.iteritems() if k > 2)
{9: 'd', 4: 'a'}
If you want to create a dictionary with subset of items, you can also use a dictionary comprehension for Python 2.7+:
>>> x = {4:"a", 1:"b", 0:"c", 9:"d"}
>>> y = {k:v for k, v in x.iteritems() if k > 2}
>>> y
{9: 'd', 4: 'a'}
This is only a newer equivalent with only minor syntax differences for what Johnysweb shows in his answer:
>>> y = dict((k, v) for k, v in x.iteritems() if k > 2)
>>> y
{9: 'd', 4: 'a'}
The following list comprehension will print the key and value if key > 2.
Try this:
print [(key, value) for key, value in x.iteritems() if key > 2]
This solution prints the key t and the value in the dictionary x at key t.
x = {4:"a", 1:"b", 0:"c", 9:"d"}
for t in x:
if t > 2:
print t, x[t]
Using lambda function
(lambda x:[(k,v) for k,v in x.iteritems() if k > 2])(x)

Searching dictionary for max value then grabbing associated key

I need help grabbing the maximum value from a dictionary. I have a dictionary of {num : [state,value] ...} and need to grab everything associated with the highest value.
#find max value in dictionary
td = {0: ['b',3], 1: ['b',6], 4: ['b',2], 3: ['b',5] }
#In this example td dict, I want to grab the key and state associated with the highest value, 6. I want to grab "1: ['b',6]"
print td
print td.keys()
print td.values()
maxval = max([v for k,[s,v] in td.iteritems()])
print maxval #correctly prints 6
Just change your max() comprehension to yield tuples with the value as the first element:
>>> max((v, k, s) for k, (s, v) in td.iteritems())
(6, 1, 'b')
So your code might look something like this:
maxval, maxnum, maxstate = max((v, k, s) for k, (s, v) in td.iteritems())
>>> td = {0: ['b',3], 1: ['b',6], 4: ['b',2], 3: ['b',5] }
>>> max(td, key=lambda k:td[k][1])
1 ## This is the key with the maximum "value"
Of course you can also get the value like this
>>> td[max(td, key=lambda k:td[k][1])]
['b', 6]
print max(td.items(), key = lambda item: item[1][1])
The key parameter takes a function, and if used it will produce the values that maximizes that function.

Categories

Resources