Python List to access dict directly [duplicate] - python

This question already has answers here:
Checking a nested dictionary using a dot notation string "a.b.c.d.e", automatically create missing levels
(5 answers)
How can I return a default value for an attribute? [duplicate]
(7 answers)
Closed 8 years ago.
I have a document like this:
>>> k = {'finance_pl':{'S':{'2008':45,'2009':34}}}
Normal way to access is:
>>> k['finance_pl']['S']
{'2008': 45, '2009': 34}
But, in my case the end user will give me input as finance_pl.S
I can split this and access the dictionary like this:
>>> doc_list = doc.split('.')
>>> k[doc_list[0]][doc_list[1]]
{'2008': 45, '2009': 34}
But, I don't want to do this, since the dictionary structure may change the and
user can give something like this finance_pl.new.S instead of k['finance_pl']['S'] or k[doc_list[0]][doc_list[1]].
I need something to apply the users input directly (Ex: if input is finance_pl.new.S, I should be able to apply this .split('.') method to the users input and apply directly).
What is the elegant way to do that ?

I'd simply loop over all the parts:
def getter(somedict, key):
parts = key.split(".")
for part in parts:
somedict = somedict[part]
return somedict
after which we have
>>> getter(k, "finance_pl.S")
{'2008': 45, '2009': 34}
or
>>> getter({"a": {"b": {"c": "d"}}}, "a")
{'b': {'c': 'd'}}
>>> getter({"a": {"b": {"c": "d"}}}, "a.b.c")
'd'

You could go for something like:
k = {'finance_pl':{'S':{'2008':45,'2009':34}}}
print reduce(dict.__getitem__, 'finance_pl.S.2009'.split('.'), k)
# 34
If you're using Python 3.x, you'll need a from functools import reduce in there...

>>> k = {'finance_pl':{'S':{'2008':45,'2009':34}}}
>>> ui = 'finance_pl.S'
>>> def getter(adict, key):
... return reduce(dict.get, key.split('.'), adict)
...
>>> getter(k, ui)
{'2008': 45, '2009': 34}
>>>

userkey = 'finance_pl.new.S'
for key in userkey.split('.'):
k = k[key]
# the final value of k is the one you want
So basically just iterate on every subkey and retrieve the inner dictionary until you're out of subkeys

Related

Converting all dictionary key/items pairs to separate lists [duplicate]

This question already has answers here:
Elegant way to unpack limited dict values into local variables in Python
(5 answers)
Closed 9 months ago.
Is there a Pythonic way to assign the values of a dictionary to its keys, in order to convert the dictionary entries into variables?
I tried this out:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec('exec(key)=val')
exec(key)=val
^
SyntaxError: invalid syntax
I am certain that the key-value pairs are correct because they were previously defined as variables by me before. I then stored these variables in a dictionary (as key-value pairs) and would like to reuse them in a different function. I could just define them all over again in the new function, but because I may have a dictionary with about 20 entries, I thought there may be a more efficient way of doing this.
You can do it in a single line with:
>>> d = {'a': 1, 'b': 2}
>>> locals().update(d)
>>> a
1
However, you should be careful with how Python may optimize locals/globals access when using this trick.
Note
I think editing locals() like that is generally a bad idea. If you think globals() is a better alternative, think it twice! :-D
Instead, I would rather always use a namespace.
With Python 3 you can:
>>> from types import SimpleNamespace
>>> d = {'a': 1, 'b': 2}
>>> n = SimpleNamespace(**d)
>>> n.a
1
If you are stuck with Python 2 or if you need to use some features missing in types.SimpleNamespace, you can also:
>>> from argparse import Namespace
>>> d = {'a': 1, 'b': 2}
>>> n = Namespace(**d)
>>> n.a
1
If you are not expecting to modify your data, you may as well consider using collections.namedtuple, also available in Python 3.
This was what I was looking for:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec(key + '=val')
You already have a perfectly good dictionary. Just use that. If you know what the keys are going to be, and you're absolutely sure this is a reasonable idea, you can do something like
a, b = d['a'], d['b']
but most of the time, you should just use the dictionary. (If using the dictionary is awkward, you are probably not organizing your data well; ask for help reorganizing it.)
you can use operator.itemgetter
>>> from operator import itemgetter
>>> d = {'a':1, 'b':2}
>>> a, b = itemgetter('a', 'b')(d)
>>> a
1
>>> b
2
Consider the "Bunch" solution in Python: load variables in a dict into namespace. Your variables end up as part of a new object, not locals, but you can treat them as variables instead of dict entries.
class Bunch(object):
def __init__(self, adict):
self.__dict__.update(adict)
d = {'a':1, 'b':2}
vars = Bunch(d)
print vars.a, vars.b
Python has great support for list unpacking, but not dict or object unpacking. The most unsurprising and Pythonic approach seems to be accessing each item by hand to build an intermediate tuple as described in this answer:
a, b = d['a'], d['b']
However, if you have a lot of properties, or variable names are long, it can get nasty to do:
great, wow, awesome = dictionary['great'], dictionary['wow'], dictionary['awesome']
For context, the JavaScript equivalent of the above (destructuring) is:
const {great, wow, awesome} = dictionary;
Here's an option that is a bit more dynamic:
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = (dictionary[k] for k in ("great", "wow", "awesome"))
>>> great
0
>>> awesome
2
This is still verbose; you could write a function to abstract things a bit, but unfortunately you still have to type everything twice:
>>> def unpack(dct, *keys):
... return (dct[k] for k in keys)
...
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = unpack(dictionary, "great", "wow", "awesome")
You can generalize this to work on objects too:
>>> def unpack(x, *keys):
... if isinstance(x, dict):
... return (x[k] for k in keys)
... return (getattr(x, k) for k in keys)
...
>>> from collections import namedtuple
>>> Foo = namedtuple("Foo", "a b c d e")
>>> foo = Foo(a=0, b=1, c=2, d=3, e=4)
>>> c, b, d, a = unpack(foo, "c", "b", "d", "a")
>>> d
3
After all is said and done, unpacking by hand on multiple lines is probably best for real production code that you need to be safe and comprehensible:
>>> great = dictionary["great"]
>>> wow = dictionary["wow"]
>>> awesome = dictionary["awesome"]
Use pandas:
import pandas as pd
var=pd.Series({'a':1, 'b':2})
#update both keys and variables
var.a=3
print(var.a,var['a'])

Access nested dictionary without loops [duplicate]

This question already has answers here:
Access nested dictionary items via a list of keys?
(20 answers)
Closed 4 years ago.
If I have a nested dictionary
mydict={'a1':{'b1':1}, 'a2':2}
and a list of indexes index = ['a1', 'b1'] leading to an inner value, is there a pythonic / one-liner way to get that value, i.e. without resorting to a verbose loop like:
d = mydict
for idx in index:
d = d[idx]
print(d)
You can use functools.reduce.
>>> from functools import reduce
>>> mydict = {'a1':{'b1':1}, 'a2':2}
>>> keys = ['a1', 'b1']
>>> reduce(dict.get, keys, mydict)
1
dict.get is a function that takes two arguments, the dict and a key (and another optional argument not relevant here). mydict is used as the initial value.
In case you ever need the intermediary results, use itertools.accumulate.
>>> from itertools import accumulate
>>> list(accumulate([mydict] + keys, dict.get))
[{'a1': {'b1': 1}, 'a2': 2}, {'b1': 1}, 1]
Unfortunately, the function does not take an optional initializer argument, so we are prepending mydict to keys.

How to take several items from dictionary [duplicate]

This question already has answers here:
Extract a subset of key-value pairs from dictionary?
(14 answers)
Filter dict to contain only certain keys?
(22 answers)
Closed 5 years ago.
Dictionary:
d = {'a':[2,3,4,5],
'b':[1,2,3,4],
'c':[5,6,7,8],
'd':[4,2,7,1]}
I want to have d_new which containes only b and c items.
d_new = {'b':[1,2,3,4],
'c':[5,6,7,8]}
I want a scalable solution
EDIT:
I also need a method to create a new dictionary by numbers of items:
d_new_from_0_to_2 = {'a':[2,3,4,5],
'b':[1,2,3,4]}
If you want a general way to pick particular keys (and their values) from a dict, you can do something like this:
d = {'a':[2,3,4,5],
'b':[1,2,3,4],
'c':[5,6,7,8],
'd':[4,2,7,1]}
selected_keys = ['a','b']
new_d = { k: d[k] for k in selected_keys }
Gives:
{'a': [2, 3, 4, 5], 'b': [1, 2, 3, 4]}
I think that in Python 2.6 and earlier you would not be able to use a dict comprehension, so you would have to use:
new_d = dict((k,d[k]) for k in selected_keys)
Is this what you want?
new_d = dict(b=d.get('b'), c=d.get('c'))

Finding a key for a certain value python [duplicate]

This question already has answers here:
Get key by value in dictionary
(43 answers)
Closed 8 years ago.
If p='hello'
I need to search the dictionary for the value 'hello' and return the key for 'hello'
Is there a certain built in function that could help me do this?
I can't think of a built-in function to do this, but the best possible way would be:
def get_keys(d, x):
return [k for k, v in adict.items() if v == x]
Demo:
>>> example = {'baz': 1, 'foo': 'hello', 'bar': 4, 'qux': 'bye'}
>>> get_keys(example, 'hello')
['foo']
We use a list here because any one value can occur multiple times in a dictionary- so we need something to hold all of the applicable corresponding keys.
With that in mind, if you only want the first found instance you would just do [0] on the returned list.
You can do:
def get_pos(my_dict, my_str):
pos = []
for i in my_dict:
if my_dict[i] == my_str:
pos.append(i)
return pos
Examples
>>> a = {'apple':'hello', 'banana':'goodbye'}
>>> get_pos(a,'hello')
'apple'

Convert dictionary entries into variables [duplicate]

This question already has answers here:
Elegant way to unpack limited dict values into local variables in Python
(5 answers)
Closed 9 months ago.
Is there a Pythonic way to assign the values of a dictionary to its keys, in order to convert the dictionary entries into variables?
I tried this out:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec('exec(key)=val')
exec(key)=val
^
SyntaxError: invalid syntax
I am certain that the key-value pairs are correct because they were previously defined as variables by me before. I then stored these variables in a dictionary (as key-value pairs) and would like to reuse them in a different function. I could just define them all over again in the new function, but because I may have a dictionary with about 20 entries, I thought there may be a more efficient way of doing this.
You can do it in a single line with:
>>> d = {'a': 1, 'b': 2}
>>> locals().update(d)
>>> a
1
However, you should be careful with how Python may optimize locals/globals access when using this trick.
Note
I think editing locals() like that is generally a bad idea. If you think globals() is a better alternative, think it twice! :-D
Instead, I would rather always use a namespace.
With Python 3 you can:
>>> from types import SimpleNamespace
>>> d = {'a': 1, 'b': 2}
>>> n = SimpleNamespace(**d)
>>> n.a
1
If you are stuck with Python 2 or if you need to use some features missing in types.SimpleNamespace, you can also:
>>> from argparse import Namespace
>>> d = {'a': 1, 'b': 2}
>>> n = Namespace(**d)
>>> n.a
1
If you are not expecting to modify your data, you may as well consider using collections.namedtuple, also available in Python 3.
This was what I was looking for:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec(key + '=val')
You already have a perfectly good dictionary. Just use that. If you know what the keys are going to be, and you're absolutely sure this is a reasonable idea, you can do something like
a, b = d['a'], d['b']
but most of the time, you should just use the dictionary. (If using the dictionary is awkward, you are probably not organizing your data well; ask for help reorganizing it.)
you can use operator.itemgetter
>>> from operator import itemgetter
>>> d = {'a':1, 'b':2}
>>> a, b = itemgetter('a', 'b')(d)
>>> a
1
>>> b
2
Consider the "Bunch" solution in Python: load variables in a dict into namespace. Your variables end up as part of a new object, not locals, but you can treat them as variables instead of dict entries.
class Bunch(object):
def __init__(self, adict):
self.__dict__.update(adict)
d = {'a':1, 'b':2}
vars = Bunch(d)
print vars.a, vars.b
Python has great support for list unpacking, but not dict or object unpacking. The most unsurprising and Pythonic approach seems to be accessing each item by hand to build an intermediate tuple as described in this answer:
a, b = d['a'], d['b']
However, if you have a lot of properties, or variable names are long, it can get nasty to do:
great, wow, awesome = dictionary['great'], dictionary['wow'], dictionary['awesome']
For context, the JavaScript equivalent of the above (destructuring) is:
const {great, wow, awesome} = dictionary;
Here's an option that is a bit more dynamic:
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = (dictionary[k] for k in ("great", "wow", "awesome"))
>>> great
0
>>> awesome
2
This is still verbose; you could write a function to abstract things a bit, but unfortunately you still have to type everything twice:
>>> def unpack(dct, *keys):
... return (dct[k] for k in keys)
...
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = unpack(dictionary, "great", "wow", "awesome")
You can generalize this to work on objects too:
>>> def unpack(x, *keys):
... if isinstance(x, dict):
... return (x[k] for k in keys)
... return (getattr(x, k) for k in keys)
...
>>> from collections import namedtuple
>>> Foo = namedtuple("Foo", "a b c d e")
>>> foo = Foo(a=0, b=1, c=2, d=3, e=4)
>>> c, b, d, a = unpack(foo, "c", "b", "d", "a")
>>> d
3
After all is said and done, unpacking by hand on multiple lines is probably best for real production code that you need to be safe and comprehensible:
>>> great = dictionary["great"]
>>> wow = dictionary["wow"]
>>> awesome = dictionary["awesome"]
Use pandas:
import pandas as pd
var=pd.Series({'a':1, 'b':2})
#update both keys and variables
var.a=3
print(var.a,var['a'])

Categories