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

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().

Related

How to create a lookup table with noise in 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']

Python dictionary assignment missing

Python stores key/values in dictionaries.
In this example values (which are dictionaries themselves) are stored in "lut".
lut = {}
pair=" "
line = "halhak"
for letter in line.strip() + ' ':
d = lut.setdefault(pair, {})
d[letter] = d.get(letter, 0) + 1
pair = pair[1] + letter
The key / values are:
for key in lut:
print key, "/", lut[key]
/ {'h': 1}
ak / {' ': 1}
al / {'h': 1}
lh / {'a': 1}
ha / {'k': 1, 'l': 1}
h / {'a': 1}
My question:
I don't see where the loop assigns any values to "lut" different from "{}".
d is always a reference to some element of lut. Here's a similar example that shows how it works.
>>> lut = {1 : {}}
>>> d = lut[1]
>>> d is lut[1]
True
lut[1] is a reference to some dictionary, and the value of d is a reference to that same dictionary, as verified by the is operator. Operations on d and operations on lut[1] operate on the same object.
In your actual code, a call to setdefault is involved:
d = lut.setdefault(pair, {})
The setdefault method does two things: if pair is not in lut, it first sets the value of lut[pair] to the given value. Then it returns the value of lut[pair]. It's identical to the following code
if pair not in lut:
lut[pair] = {}
d = lut[pair]
Only empty dicts {} are directly added to lut, using setdefault().
As described in the documentation, setdefault always returns a value for any given key:
setdefault(key[, default])
If key is in the dictionary, return its value.
If not, insert key with a value of default and return default. default defaults to None.
So d is always a dict - one of the values in the outer lut dict.
However, the next line modifies one of these (initially empty) dicts out of lut,
which is why you see populated dicts in the results.
The expression d = lut.setdefault(pair, {}) does one of two things, depending on wether or not the pair key is present:
pair is present; return a reference to the value
pair is not present; set lut[pair] to the second argument ({}), and return it.
Either way, you now have a reference to the object referenced by lut[pair], which is always a dictionary.
Modifying that dictionary means that all references everywhere can see those changes. d[letter] = d.get(letter, 0) + 1 will set a key-value pair in that dictionary. Since both d and lut[pair] reference that dictionary, you can later iterate over lut to see those changes.
A quick demo:
>>> lut = {}
>>> d = lut.setdefault('foo', {})
>>> lut
{'foo': {}}
>>> d
{}
>>> d is lut['foo']
True
>>> d['bar'] = 42
>>> d
{'bar': 42}
>>> lut
{'foo': {'bar': 42}}
>>> lut['foo']
{'bar': 42}

Python dictionary view

Is a dictionary the right type for data where I want to look up entries based on an index, e.g.
dictlist = {}
dictlist['itemid' + '1'] = {'name':'AAA', 'class':'Class1', 'nonstandard':'whatever'}
dictlist['itemid' + '2'] = {'name':'BBB', 'class':'Class2', 'maynotbehere':'optional'}
dictlist['itemid' + '3'] = {'name':'CCC', 'class':'Class3', 'regular':'or not'}
I can now address a specific item, e.g.
finditem='itemid2'
dictitem = {}
try:
dictitem[finditem] = dictlist[finditem]
print dictitem
except KeyError:
print "Nothing there"
Is that the right way to create such a lookup table in python?
If I now wanted to print the data, but only the Item ID, and an associated dictionary with only name and class "properties", how can I do that?
I am looking for something that will create a new dictionary by copying the desired properties only, or else present a limited view of the existing dictionary, as if the unspecified properties were not there. So for example
view(dictlist, 'name', 'class')
will return a dictionary that displays a restricted view of the list, showing only the name and class keys. I have tried
view = {}
for item in dictlist:
view[item] = {dictlist[item]['name'], dictlist[item]['class']}
print view
Which returns
{'itemid1': set(['AAA', 'Class1']), 'itemid3': set(['Class3', 'CCC']), 'itemid2': set(['Class2', 'BBB'])}
Instead of
{'itemid1': {'name':'AAA', 'class':'Class1'}, 'itemid3': {'name':'CCC', 'class':'Class3'}, 'itemid2': {'name':'BBB', 'class':'Class2'} }
Note that {'foo', 'bar'} is a set literal, not a dictionary literal, as it does not have the key: value syntax required for a dictionary:
>>> type({'foo', 'bar'})
<class 'set'>
>>> type({'foo': 'bar'})
<class 'dict'>
You need to be more careful with your syntax generally; I have no idea what the random closing square brackets ] are doing in the output you claim you want, and it's missing a closing brace }.
You could extend your current code to do keys and values as follows:
for item in dictlist:
view[item] = {'name': dictlist[item]['name'],
'class': dictlist[item]['class']}
but a more generic function would look like:
def view(dictlist, *keys):
output = {}
for item in dictlist:
output[item] = {}
for key in keys:
output[item][key] = dictlist[item].get(key)
return output
note the use of dict.get to handle missing keys gracefully:
>>> d = {'foo': 'bar'}
>>> d.get('foo')
'bar' # returns the value if key present, or
>>> d.get('baz')
>>> # returns None by default
or, using a "dictionary comprehension":
def view(dictlist, *keys):
return {k1: {k2: v2 for k2, v2 in v1.items() if k2 in keys}
for k1, v1 in dictlist.items()}
(This will exclude missing keys from the output, whereas the previous code will include them with None value - which is preferable will depend on your use case.)
Note the use of *keys to take an arbitrary number of positional arguments:
>>> def test(d, *keys):
print(keys)
>>> test({}, "foo", "bar", "baz")
('foo', 'bar', 'baz')

How to find dictionary key with the lowest value where key is in a list

I'm trying to get the key with the lowest value in a dictionary where the key is in a separate list. I also fear that initializing my variable "key" in the way I am might cause trouble in the future, even though I don't think it will.
d = { "a":3, "b":2, "c":7 }
l = ["a","b"]
key = l[0]
for c in l:
key = c if d[c] < d[key] else key
print key
I'm still trying to get a handle on list comprehension. I have tried something like this to replace the for loop and everything, but it didn't work:
key = c if d[c] < d[key] else key for c in l
Ended with an invalid syntax error.
Use the key parameter to the min() function to pick out a lowest key:
min(l, key=d.__getitem__)
The key parameter must be a callable that maps items in the input list to a value by which you want to pick the minimum item. In your example, 'b' is the lowest item because d maps it to 2, while 'a' is mapped to 3.
Demo:
>>> d = { "a":3, "b":2, "c":7 }
>>> l = ["a","b"]
>>> min(l, key=d.__getitem__)
'b'
If there is any value in l that is not listed in d, d.__getitem__ will raise a KeyError:
>>> min(['a', 'b', 'e'], key=d.__getitem__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'e'
You could also use lambda i: d[i] to get the same effect without scary direct use of dunder (double-underscore) special methods.
If you want to ignore non-existent keys, use:
min(['a', 'b', 'e'], key=lambda i: d.get(i, float('inf'))
float('inf') is guaranteed to always be larger than any other number, so in the above example 'e' will not be considered a minimum because it doesn't exist in d.

index python dictionary by value [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inverse dictionary lookup - Python
Is there a built in way to index a dictionary by value in Python.
e.g. something like:
dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print key where dict[key] == 'apple'
or:
dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print key where 'apple' in dict[key]
or do I have to manually loop it?
You could use a list comprehension:
my_dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print [key for key, value in my_dict.items() if value == 'apple']
The code above is doing almost exactly what said you want:
print key where dict[key] == 'apple'
The list comprehension is going through all the key, value pairs given by your dictionary's items method, and making a new list of all the keys where the value is 'apple'.
As Niklas pointed out, this does not work when your values could potentially be lists. You have to be careful about just using in in this case since 'apple' in 'pineapple' == True. So, sticking with a list comprehension approach requires some type checking. So, you could use a helper function like:
def equals_or_in(target, value):
"""Returns True if the target string equals the value string or,
is in the value (if the value is not a string).
"""
if isinstance(target, str):
return target == value
else:
return target in value
Then, the list comprehension below would work:
my_dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print [key for key, value in my_dict.items() if equals_or_in('apple', value)]
You'll have to manually loop it, but if you'll need the lookup repeatedly this is a handy trick:
d1 = {'fruit':'apple','colour':'blue','meat':'beef'}
d1_rev = dict((v, k) for k, v in d1.items())
You can then use the reverse dictionary like this:
>>> d1_rev['blue']
'colour'
>>> d1_rev['beef']
'meat'
Your requirements are more complex than you realize:
You need to handle both list values and plain values
You don't actually need to get back a key, but a list of keys
You could solve this in two steps:
normalize the dict so that every value is a list (every plain value becomes a single-element)
build a reverse dictionary
The following functions will solve this:
from collections import defaultdict
def normalize(d):
return { k:(v if isinstance(v, list) else [v]) for k,v in d.items() }
def build_reverse_dict(d):
res = defaultdict(list)
for k,values in normalize(d).items():
for x in values:
res[x].append(k)
return dict(res)
To be used like this:
>>> build_reverse_dict({'fruit':'apple','colour':'blue','meat':'beef'})
{'blue': ['colour'], 'apple': ['fruit'], 'beef': ['meat']}
>>> build_reverse_dict({'fruit':['apple', 'banana'], 'colour':'blue'})
{'blue': ['colour'], 'apple': ['fruit'], 'banana': ['fruit']}
>>> build_reverse_dict({'a':'duplicate', 'b':['duplicate']})
{'duplicate': ['a', 'b']}
So you just build up the reverse dictionary once and then lookup by value and get back a list of keys.

Categories

Resources