print dict keys and values using another variable - python-2.7

I have dict 'SR' as given below.
>>> SR = {'threshold':'95', 'math':'mean', 'dir':'down'}
>>> SR
{'threshold': '95', 'dir': 'down', 'math': 'mean'}
>>> var='SR'
How can i print all key & value of 'SR' using variable var . My script dynamically select dict name based on some logic , store it in some variable . So I have to print dict values and keys using an another variable. Please help .

Put the various dicts into another dict and look it up that way.
d = {
'SR': {'threshold': '95', 'math': 'mean', 'dir': 'down'},
'AB': {'foo': 'bar'},
'XY': {'blah': 'baz'},
}
which_to_print = 'SR'
for key, value in d[which_to_print].items():
print key, value

Related

Python 2.7 create a dictionary from dotted values [duplicate]

I'm trying to programmatically set a value in a dictionary, potentially nested, given a list of indices and a value.
So for example, let's say my list of indices is:
['person', 'address', 'city']
and the value is
'New York'
I want as a result a dictionary object like:
{ 'Person': { 'address': { 'city': 'New York' } }
Basically, the list represents a 'path' into a nested dictionary.
I think I can construct the dictionary itself, but where I'm stumbling is how to set the value. Obviously if I was just writing code for this manually it would be:
dict['Person']['address']['city'] = 'New York'
But how do I index into the dictionary and set the value like that programmatically if I just have a list of the indices and the value?
Python
Something like this could help:
def nested_set(dic, keys, value):
for key in keys[:-1]:
dic = dic.setdefault(key, {})
dic[keys[-1]] = value
And you can use it like this:
>>> d = {}
>>> nested_set(d, ['person', 'address', 'city'], 'New York')
>>> d
{'person': {'address': {'city': 'New York'}}}
I took the freedom to extend the code from the answer of Bakuriu. Therefore upvotes on this are optional, as his code is in and of itself a witty solution, which I wouldn't have thought of.
def nested_set(dic, keys, value, create_missing=True):
d = dic
for key in keys[:-1]:
if key in d:
d = d[key]
elif create_missing:
d = d.setdefault(key, {})
else:
return dic
if keys[-1] in d or create_missing:
d[keys[-1]] = value
return dic
When setting create_missing to True, you're making sure to only set already existing values:
# Trying to set a value of a nonexistent key DOES NOT create a new value
print(nested_set({"A": {"B": 1}}, ["A", "8"], 2, False))
>>> {'A': {'B': 1}}
# Trying to set a value of an existent key DOES create a new value
print(nested_set({"A": {"B": 1}}, ["A", "8"], 2, True))
>>> {'A': {'B': 1, '8': 2}}
# Set the value of an existing key
print(nested_set({"A": {"B": 1}}, ["A", "B"], 2))
>>> {'A': {'B': 2}}
Here's another option:
from collections import defaultdict
recursivedict = lambda: defaultdict(recursivedict)
mydict = recursivedict()
I originally got this from here: Set nested dict value and create intermediate keys.
It is quite clever and elegant if you ask me.
First off, you probably want to look at setdefault.
As a function I'd write it as
def get_leaf_dict(dct, key_list):
res=dct
for key in key_list:
res=res.setdefault(key, {})
return res
This would be used as:
get_leaf_dict( dict, ['Person', 'address', 'city']) = 'New York'
This could be cleaned up with error handling and such. Also using *args rather than a single key-list argument might be nice; but the idea is that
you can iterate over the keys, pulling up the appropriate dictionary at each level.
Here is my simple solution: just write
terms = ['person', 'address', 'city']
result = nested_dict(3, str)
result[terms] = 'New York' # as easy as it can be
You can even do:
terms = ['John', 'Tinkoff', '1094535332'] # account in Tinkoff Bank
result = nested_dict(3, float)
result[terms] += 2375.30
Now the backstage:
from collections import defaultdict
class nesteddict(defaultdict):
def __getitem__(self, key):
if isinstance(key, list):
d = self
for i in key:
d = defaultdict.__getitem__(d, i)
return d
else:
return defaultdict.__getitem__(self, key)
def __setitem__(self, key, value):
if isinstance(key, list):
d = self[key[:-1]]
defaultdict.__setitem__(d, key[-1], value)
else:
defaultdict.__setitem__(self, key, value)
def nested_dict(n, type):
if n == 1:
return nesteddict(type)
else:
return nesteddict(lambda: nested_dict(n-1, type))
The dotty_dict library for Python 3 can do this. See documentation, Dotty Dict for more clarity.
from dotty_dict import dotty
dot = dotty()
string = '.'.join(['person', 'address', 'city'])
dot[string] = 'New York'
print(dot)
Output:
{'person': {'address': {'city': 'New York'}}}
Use these pair of methods
def gattr(d, *attrs):
"""
This method receives a dict and list of attributes to return the innermost value of the give dict
"""
try:
for at in attrs:
d = d[at]
return d
except:
return None
def sattr(d, *attrs):
"""
Adds "val" to dict in the hierarchy mentioned via *attrs
For ex:
sattr(animals, "cat", "leg","fingers", 4) is equivalent to animals["cat"]["leg"]["fingers"]=4
This method creates necessary objects until it reaches the final depth
This behaviour is also known as autovivification and plenty of implementation are around
This implementation addresses the corner case of replacing existing primitives
https://gist.github.com/hrldcpr/2012250#gistcomment-1779319
"""
for attr in attrs[:-2]:
# If such key is not found or the value is primitive supply an empty dict
if d.get(attr) is None or isinstance(d.get(attr), dict):
d[attr] = {}
d = d[attr]
d[attrs[-2]] = attrs[-1]
Here's a variant of Bakuriu's answer that doesn't rely on a separate function:
keys = ['Person', 'address', 'city']
value = 'New York'
nested_dict = {}
# Build nested dictionary up until 2nd to last key
# (Effectively nested_dict['Person']['address'] = {})
sub_dict = nested_dict
for key_ind, key in enumerate(keys[:-1]):
if not key_ind:
# Point to newly added piece of dictionary
sub_dict = nested_dict.setdefault(key, {})
else:
# Point to newly added piece of sub-dictionary
# that is also added to original dictionary
sub_dict = sub_dict.setdefault(key, {})
# Add value to last key of nested structure of keys
# (Effectively nested_dict['Person']['address']['city'] = value)
sub_dict[keys[-1]] = value
print(nested_dict)
>>> {'Person': {'address': {'city': 'New York'}}}
This is a pretty good use case for a recursive function. So you can do something like this:
def parse(l: list, v: str) -> dict:
copy = dict()
k, *s = l
if len(s) > 0:
copy[k] = parse(s, v)
else:
copy[k] = v
return copy
This effectively pops off the first value of the passed list l as a key for the dict copy that we initialize, then runs the remaining list through the same function, creating a new key under that key until there's nothing left in the list, whereupon it assigns the last value to the v param.
This is much easier in Perl:
my %hash;
$hash{"aaa"}{"bbb"}{"ccc"}=1; # auto creates each of the intermediate levels
# of the hash (aka: dict or associated array)

How to delete the first element of a row so that the whole row deleted from a list?

My list looks as follow:
items = []
a = "apple", 1.23
items.append(a)
b = "google", 2.33
items.append(b)
c = "ibm", 4.35
items.append(c)
Now I will just remove the row of "apple" by just giving the name of "apple".
How to do?
You can convert items into a dictionary, delete the entry with key apple and return the dictionary items:
>>> items
[('apple', 1.23), ('google', 2.33), ('ibm', 4.35)]
>>> d = dict(items)
>>> del d['apple']
>>> items = d.items()
>>> items
[('ibm', 4.35), ('google', 2.33)]
In python 3, you should cast d.items with list as .items() returns a dict_items object which is iterable but not subscriptable:
>>> items = list(d.items())
I suggest that you use a proper data structure. In your case, a dict will do the trick.
items = {"apple": 1.23, "google": 2.33, "ibm": 4.35}
To delete, use:
items.pop("apple", None)
Since I canonly accept one answer and truely to say I am not 100% satisfied with both, so I haven't accpted any one. Hope it's OK for you all.
I do followings, a combination of both of yours:
d = dict(items)
d.pop("apple", None)
myitem = d.items()
I think the best approach is that of using a dictionary, as suggested by #Sricharan Madasi and #Moses Koledoye. However, provided that the OP seems to prefer to arrange data as a list of tuples, he may find this function useful:
def my_func(lst, key):
return [(name, number) for (name, number) in lst if name != key]
The following interactive session demonstrates its usage:
>>> items = [('apple', 1.23), ('google', 2.33), ('ibm', 4.35)]
>>> my_func(items, 'apple')
[('google', 2.33), ('ibm', 4.35)]
>>> my_func(items, 'ibm')
[('apple', 1.23), ('google', 2.33)]
>>> my_func(items, 'foo')
[('apple', 1.23), ('google', 2.33), ('ibm', 4.35)]

Turning weekly to monthly data in Python dictionary

I'm trying to turn this dictionary:
dic = {'2007-10-21': '53', '2007-10-28': '50', '2007-11-05': '100','2007-11-06': '99'}
Into something like this:
dic = {'2007-10': '103', '2007-11': '199'}
Since I need to do that in scale, pythonly speaking I need to sum all the values which its keys start with the same 7 characters.
Try this,
__author__ = 'Fawzan'
dic = {'2007-10-21': '53', '2007-10-28': '50', '2007-11-05': '100', '2007-11-06': '99'}
# create a new dictionary
newDic = {}
# iterate the old dictionary
for key in dic:
# get the desiresd string for comparision
k = key[0:7]
# for debug
print(k)
# if the key is already in the new dictionary, then add the value to existing key
if (k in newDic):
newDic[k] += float(dic[key])
# else append the key, value
else:
newDic[k] = float(dic[key])
# print and check the answer :)
print(newDic)

Python do a lookup between 2 dictionaries

I am trying to summarise two dictionaries as follows:
mydict = {41100: 'Health Grant',
50050: 'Salaries',
50150: 'Salaries',
50300: 'Salaries'};
mytb = {'': '',
41100: -3,450,200.40,
50050: 1,918,593.96,
50150: 97.50,
50300: 8,570.80}
My output should be:
{ 'Health Grant': -3450200.40, 'Salaries': 1927262.26 }
Can you help with coding the for loop code pls?
Just iterate the keys and values of the first dict and add the values from the second dict corresponding to the same key.
mydict = {41100: 'Health Grant', 50050: 'Salaries', 50150: 'Salaries', 50300: 'Salaries'};
mytb = {'': '', 41100: -3450200.40, 50050: 1918593.96, 50150: 97.50, 50300: 8570.80}
result = {}
for key, value in mydict.items():
result[value] = result.get(value, 0) + mytb[key]
Or using collections.defaultdict:
from collections import defaultdict
result = defaultdict(int)
for key, value in mydict.items():
result[value] += mytb[key]
In both cases, result will be {'Health Grant': -3450200.4, 'Salaries': 1927262.26}

How do I create a dictionary mapping strings to sets given a list and a tuple of tuples?

I am trying to create a dictionary from a list and tuple of tuples as illustrated below. I have to reverse map the tuples to the list and create a set of non-None column names.
Any suggestions on a pythonic way to achieve the solution (desired dictionary) is much appreciated.
MySQL table 'StateLog':
Name NY TX NJ
Amy 1 None 1
Kat None 1 1
Leo None None 1
Python code :
## Fetching data from MySQL table
#cursor.execute("select * from statelog")
#mydataset = cursor.fetchall()
## Fetching column names for mapping
#state_cols = [fieldname[0] for fieldname in cursor.description]
state_cols = ['Name', 'NY', 'TX', 'NJ']
mydataset = (('Amy', '1', None, '1'), ('Kat', None, '1', '1'), ('Leo', None, None, '1'))
temp = [zip(state_cols, each) for each in mydataset]
# Looks like I can't do a tuple comprehension for the following snippet : finallist = ((eachone[1], eachone[0]) for each in temp for eachone in each if eachone[1] if eachone[0] == 'Name')
for each in temp:
for eachone in each:
if eachone[1]:
if eachone[0] == 'Name':
k = eachone[1]
print k, eachone[0]
print '''How do I get a dictionary in this format'''
print '''name_state = {"Amy": set(["NY", "NJ"]),
"Kat": set(["TX", "NJ"]),
"Leo": set(["NJ"])}'''
Output so far :
Amy Name
Amy NY
Amy NJ
Kat Name
Kat TX
Kat NJ
Leo Name
Leo NJ
Desired dictionary :
name_state = {"Amy": set(["NY", "NJ"]),
"Kat": set(["TX", "NJ"]),
"Leo": set(["NJ"])}
To be really honest, I would say your problem is that your code is becoming too cumbersome. Resist the temptation of "one-lining" it and create a function. Everything will become way easier!
mydataset = (
('Amy', '1', None, '1'),
('Kat', None, '1', '1'),
('Leo', None, None, '1')
)
def states(cols, data):
"""
This function receives one of the tuples with data and returns a pair
where the first element is the name from the tuple, and the second
element is a set with all matched states. Well, at least *I* think
it is more readable :)
"""
name = data[0]
states = set(state for state, value in zip(cols, data) if value == '1')
return name, states
pairs = (states(state_cols, data) for data in mydataset)
# Since dicts can receive an iterator which yields pairs where the first one
# will become a key and the second one will become the value, I just pass
# a list with all pairs to the dict constructor.
print dict(pairs)
The result is:
{'Amy': set(['NY', 'NJ']), 'Leo': set(['NJ']), 'Kat': set(['NJ', 'TX'])}
Looks like another job for defaultdict!
So lets create our default dict
name_state = collections.defaultdict(set)
We now have a dictionary that has sets as all default values, we can now do something like this
name_state['Amy'].add('NY')
Moving on you just need to iterate over your object and add to each name the right states. Enjoy
You can do this as a dictionary comprehension (Python 2.7+):
from itertools import compress
name_state = {data[0]: set(compress(state_cols[1:], data[1:])) for data in mydataset}
or as a generator expression:
name_state = dict((data[0], set(compress(state_cols[1:], data[1:]))) for data in mydataset)