Beginner Python Problems - python

Just getting started with python, trying to nest a dict inside other data structures, lists, sets, etc. When I nest the dict (like, if I create a list of dicts), I cant seem to reference the keys or values inside the individual dicts anymore. Is this a design feature or am I totally boning it?

You can absolutely do this with Python. You can use the [] operator more than once -- if a is a list, then a[0] is its first element. If that first element happens to be a dict, then you can see its keys with a[0].keys(), and you can get the values out of it like this: a[0]["here's a key"]
And just like you would loop over the keys of a dictionary like this:
for key in my_dict:
# get the value
val = my_dict[key]
# do something with it
You can use an element of a list, if it happens to be a dict:
for key in a[0]:
# get the value
val = a[0][key]
# do something with it
You can make lists of lists, lists of dicts, or even dicts where the values are lists (or more dicts), pretty easily. And to reference into them, you can either iterate over their values, or chain [] operations as needed.
About the only thing that you can't do is to use lists or dicts as keys to another dict. One of the rules is that dictionary keys have to be immutable. Numbers are OK, strings are OK, tuples are OK, but lists and dicts are not.
Here's a sample of interactive code, to show you how to build up lists of dicts, and extract their values again:
# Here's a dictionary
a = { 'key1': 'value1', 'key2': 2 }
# Check it out
>>> type(a)
<type 'dict'>
# Print it:
>>> a
{'key1': 'value1', 'key2': 2}
# Look inside
>>> a['key1']
'value1'
# Here's another one
b = { 'abc': 123, 'def': 456 }
# Now let's make a list of them
c = [a, b]
# Check that out, too
>>> type(c)
<type 'list'>
# Print it:
>>> c
[{'key1': 'value1', 'key2': 2}, {'def': 456, 'abc': 123}]
>>> c[0]
{'key1': 'value1', 'key2': 2}
# Dig deeper
>>> c[0]['key1']
'value1'

When you have nested dicts (or nested anything for that matter), you have to provide the index of the desired dict in the outside list, and then the index of the desired item. So, if you had a couple dicts in a list:
list_of_dicts = [{'a':1,'b':2,'c':3},{'d':4,'e':5,'f':6}]
to access element 'e' of the second dict, you would enter: list_of_dicts[1]['e']

To touch on a few things:
Adding a dict to a list.
mylist = []
mylist.append({'key1': 'val1'})
Adding a list to a set.
myset = set()
myset.add({'key1': 'val1'}) # Error - dicts are mutable, therefore not hashable.
Keeping track of distinct dictionaries.
mydicts = set([id(d) for d in mylist])
Retrieving elements.
# With Lists
mylist[0]['key1']
# With Sets
mydicts[0] # Error - sets do not support indexing.

x = [{"a":1},{"b":2}]
>>> x[1]["b"]
2

Related

Iteratively adding new lists as values to a dictionary

I have created a dictionary (dict1) which is not empty and contains keys with corresponding lists as their values. I want to create a new dictionary (dict2) in which new lists modified by some criterion should be stored as values with the corresponding keys from the original dictionary. However, when trying to add the newly created list (list1) during every loop iteratively to the dictionary (dict2) the stored values are empty lists.
dict1 = {"key1" : [-0.04819, 0.07311, -0.09809, 0.14818, 0.19835],
"key2" : [0.039984, 0.0492105, 0.059342, -0.0703545, -0.082233],
"key3" : [0.779843, 0.791255, 0.802576, 0.813777, 0.823134]}
dict2 = {}
list1 = []
for key in dict1:
if (index + 1 < len(dict1[key]) and index - 1 >= 0):
for index, element in enumerate(dict1[key]):
if element - dict1[key][index+1] > 0:
list1.append(element)
dict2['{}'.format(key)] = list1
list.clear()
print(dict2)
The output I want:
dict2 = {"key1" : [0.07311, 0.14818, 0.19835],
"key2" : [0.039984, 0.0492105, 0.059342],
"key3" : [0.779843, 0.791255, 0.802576, 0.813777, 0.823134]}
The problem is that list always refers to the same list, which you empty by calling clear. Therefore all values in the dict refer to the same empty list object in memory.
>>> # ... running your example ...
>>> [id(v) for v in dict2.values()]
[2111145975936, 2111145975936, 2111145975936]
It looks like you want to filter out negative elements from the values in dict1. A simple dict-comprehension will do the job.
>>> dict2 = {k: [x for x in v if x > 0] for k, v in dict1.items()}
>>> dict2
{'key1': [0.07311, 0.14818, 0.19835],
'key2': [0.039984, 0.0492105, 0.059342],
'key3': [0.779843, 0.791255, 0.802576, 0.813777, 0.823134]}
#timgeb gives a great solution which simplifies your code to a dictionary comprehension but doesn't show how to fix your existing code. As he says there, you are reusing the same list on each iteration of the for loop. So to fix your code, you just need to create a new list on each iteration instead:
for key in dict1:
my_list = []
# the rest of the code is the same, expect you don't need to call clear()

Python Dictionary append value error

I'm trying to append a value (list) to a dictionary unsuccessfully. setting the value by 'equal' works, but appending doesn't.
DurationDict = dict()
DurationDict[str(curYear)] = duration // This works
DurationDict[str(curYear)].append(duration) //This does't work.
any ideas?
If you want to append to the value of dictionary, then value should be a type of list.
lets consider following example:
>>> k = {"a":1}
>>> k["b"] = 2
>>> k["c"] = [2]
>>> k["c"].append("new value") # here you can append because value of c is type of list.
>>> print(k)
{'a': 1, 'c': [2, 'new value'], 'b': 2}
>>> k["b"].append("new value") # here you can not append because value of b is type of int
you can append to a list but not to a dict. python dicts are documented here.
if you want to have a list for all your dictionary entries, you can use defaultdict:
collections import defaultdict
DurationDict = defaultdict(list)
DurationDict[str(curYear)].append(duration)
defaultdict works like a normal dict except it returns the result of the 'factory' - in this case list() if the key you are looking up does not exist yet. you can then append to this (empty) list.
You can only append lists. If you have an empty dictionary d,
d = {} # initialize an empty dictionary
d['a'].append(1) # will NOT work
But if you already had an empty list defined,
d = {'a': []} # initialize with an empty list
df['a'].append(1) # will work
>>> d
{'a': [1]}

combining a list of dictionaries with another dictionary

I have a list with a set amount of dictionaries inside which I have to compare to one other dictionary.
They have the following form (there is no specific form or pattern for keys and values, these are randomly chosen examples):
list1 = [
{'X1': 'Q587', 'X2': 'Q67G7', ...},
{'AB1': 'P5K7', 'CB2': 'P678', ...},
{'B1': 'P6H78', 'C2': 'BAA5', ...}]
dict1 = {
'X1': set([B00001,B00020,B00010]),
'AB1': set([B00001,B00007,B00003]),
'C2': set([B00001,B00002,B00003]), ...
}
What I want to have now is a new dictionary which has as keys: the values of the dictionaries in list1. and as values the values of dict1. And this only when the keys intersect in compared dictionaries.
I have done this in the following way:
nDicts = len(list1)
resultDict = {}
for key in range(0,nDicts):
for x in list1[key].keys():
if x in dict1.keys():
resultDict.update{list1[key][x]:dict1[x]}
print resultDict
The desired output should be of the form:
resulDict = {
'Q587': set([B00001,B00020,B00010]),
'P5K7': set([B00001,B00007,B00003]),
'BAA5': set([B00001,B00002,B00003]), ...
}
This works but since the amount of data is so high this takes forever.
Is there a better way to do this?
EDIT: I have changed the input values a little, the only ones that matter are the keys which intersect between the dictionaries within list1 and those within dict1.
The keys method in Python 2.x makes a list with a copy of all of the keys, and you're doing this not only for each dict in list1 (probably not a big deal, but it's hard to know for sure without knowing your data), but also doing it for dict1 over and over again.
On top of that, doing an in test on a list takes a long time, because it has to check each value in the list until it finds a match, but doing an in test on a dictionary is nearly instant, because it just has to look up the hash value.
Both keys are actually completely unnecessary—iterating a dict gives you the keys in order (an unspecified order, but the same is true for calling keys()), and in-checking a dict searches the same keys you'd get with keys(). So, just removing them does the same thing, but simpler, faster, and with less memory used. So:
for key in range(0,nDicts):
for x in list1[key]:
if x in dict1:
resultDict={list1[key][x]:dict1[x]}
print resultDict
There are also ways you can simplify this that probably won't help performance that much, but are still worth doing.
You can iterate directly over list1 instead of building a huge list of all the indices and iterating that.
for list1_dict in list1:
for x in list1_dict:
if x in dict1:
resultDict = {list_dict[x]: dict1[x]}
print resultDict
And you can get the keys and values in a single step:
for list1_dict in list1:
for k, v in list1_dict.iteritems():
if k in dict1:
resultDict = {v: dict1[k]}
print resultDict
Also, if you expect most of the values to be found, it will take about twice as long to first check for the value and then look it up as it would to just try to look it up and handle failure. (This is not true if most of the values will not be found, however.) So:
for list1_dict in list1:
for k, v in list1_dict.iteritems():
try:
resultDict = {v: dict1[k]}
print resultDict
except KeyError:
pass
You can simplify and optimize your operation with set intersections; as of Python 2.7 dictionaries can represent keys as sets using the dict.viewkeys() method, or dict.keys() in Python 3:
resultDict = {}
for d in list1:
for sharedkey in d.viewkeys() & dict1:
resultDict[d[sharedkey]] = dict1[sharedkey]
This can be turned into a dict comprehension even:
resultDict = {d[sharedkey]: dict1[sharedkey]
for d in list1 for sharedkey in d.viewkeys() & dict1}
I am assuming here you wanted one resulting dictionary, not a new dictionary per shared key.
Demo on your sample input:
>>> list1 = [
... {'X1': 'AAA1', 'X2': 'BAA5'},
... {'AB1': 'AAA1', 'CB2': 'BAA5'},
... {'B1': 'AAA1', 'C2': 'BAA5'},
... ]
>>> dict1 = {
... 'X1': set(['B00001', 'B00002', 'B00003']),
... 'AB1': set(['B00001', 'B00002', 'B00003']),
... }
>>> {d[sharedkey]: dict1[sharedkey]
... for d in list1 for sharedkey in d.viewkeys() & dict1}
{'AAA1': set(['B00001', 'B00002', 'B00003'])}
Note that both X1 and AB1 are shared with dictionaries in list1, but in both cases, the resulting key is AAA1. Only one of these wins (the last match), but since both values in dict1 are exactly the same anyway that doesn't make any odds in this case.
If you wanted separate dictionaries per dictionary in list1, simply move the for d in list1: loop out:
for d in list1:
resultDict = {d[sharedkey]: dict1[sharedkey] for sharedkey in d.viewkeys() & dict1}
if resultDict: # can be empty
print resultDict
If you really wanted one dictionary per shared key, move another loop out:
for d in list1:
for sharedkey in d.viewkeys() & dict1:
resultDict = {d[sharedkey]: dict1[sharedkey]}
print resultDict
#!/usr/bin/env python
list1 = [
{'X1': 'AAA1', 'X2': 'BAA5'},
{'AB1': 'AAA1', 'CB2': 'BAA5'},
{'B1': 'AAA1', 'C2': 'BAA5'}
]
dict1 = {
'X1': set(['B00001','B00002','B00003']),
'AB1': set(['B00001','B00002','B00003'])
}
g = ( k.iteritems() for k in list1)
ite = ((a,b) for i in g for a,b in i if dict1.has_key(a))
d = dict(ite)
print d

extracting dictionary pairs based on value

I want to copy pairs from this dictionary based on their values so they can be assigned to new variables. From my research it seems easy to do this based on keys, but in my case the values are what I'm tracking.
things = ({'alpha': 1, 'beta': 2, 'cheese': 3, 'delta': 4})
And in made-up language I can assign variables like so -
smaller_things = all values =3 in things
You can use .items() to traverse through the pairs and make changes like this:
smaller_things = {}
for k, v in things.items():
if v == 3:
smaller_things[k] = v
If you want a one liner and only need the keys back, list comprehension will do it:
smaller_things = [k for k, v in things.items() if v == 3]
>>> things = { 'a': 3, 'b': 2, 'c': 3 }
>>> [k for k, v in things.items() if v == 3]
['a', 'c']
you can just reverse the dictionary and pull from that:
keys_values = { 1:"a", 2:"b"}
values_keys = dict(zip(keys_values.values(), keys_values.keys()))
print values_keys
>>> {"a":1, "b":2}
That way you can do whatever you need to with standard dictionary syntax.
The potential drawback is if you have non-unique values in the original dictionary; items in the original with the same value will have the same key in the reversed dictionary, so you can't guarantee which of the original keys would be the new value. And potentially some values are unhashable (such as lists).
Unless you have a compulsive need to be clever, iterating over items is easier:
for key, val in my_dict.items():
if matches_condition(val):
do_something(key)
kindly this answer is as per my understanding of your question .
The dictionary is a kind of hash table , the main intension of dictionary is providing the non integer indexing to the values . The keys in dictionary are just like indexes .
for suppose consider the "array" , the elements in array are addressed by the index , and we have index for the elements not the elements for index . Just like that we have keys(non integer indexes) for values in dictionary .
And there is one implication the values in dictionary are non hashable I mean the values in dictionary are mutable and keys in dictionary are immutable ,simply values could be changed any time .
simply it is not good approach to address any thing by using values in dictionary

Converting Dictionary to List? [duplicate]

This question already has answers here:
How can I convert a dictionary into a list of tuples?
(13 answers)
Closed 3 years ago.
I'm trying to convert a Python dictionary into a Python list, in order to perform some calculations.
#My dictionary
dict = {}
dict['Capital']="London"
dict['Food']="Fish&Chips"
dict['2012']="Olympics"
#lists
temp = []
dictList = []
#My attempt:
for key, value in dict.iteritems():
aKey = key
aValue = value
temp.append(aKey)
temp.append(aValue)
dictList.append(temp)
aKey = ""
aValue = ""
That's my attempt at it... but I can't work out what's wrong?
dict.items()
Does the trick.
Converting from dict to list is made easy in Python. Three examples:
>> d = {'a': 'Arthur', 'b': 'Belling'}
>> d.items()
[('a', 'Arthur'), ('b', 'Belling')]
>> d.keys()
['a', 'b']
>> d.values()
['Arthur', 'Belling']
Your problem is that you have key and value in quotes making them strings, i.e. you're setting aKey to contain the string "key" and not the value of the variable key. Also, you're not clearing out the temp list, so you're adding to it each time, instead of just having two items in it.
To fix your code, try something like:
for key, value in dict.iteritems():
temp = [key,value]
dictlist.append(temp)
You don't need to copy the loop variables key and value into another variable before using them so I dropped them out. Similarly, you don't need to use append to build up a list, you can just specify it between square brackets as shown above. And we could have done dictlist.append([key,value]) if we wanted to be as brief as possible.
Or just use dict.items() as has been suggested.
You should use dict.items().
Here is a one liner solution for your problem:
[(k,v) for k,v in dict.items()]
and result:
[('Food', 'Fish&Chips'), ('2012', 'Olympics'), ('Capital', 'London')]
or you can do
l=[]
[l.extend([k,v]) for k,v in dict.items()]
for:
['Food', 'Fish&Chips', '2012', 'Olympics', 'Capital', 'London']
>>> a = {'foo': 'bar', 'baz': 'quux', 'hello': 'world'}
>>> list(reduce(lambda x, y: x + y, a.items()))
['foo', 'bar', 'baz', 'quux', 'hello', 'world']
To explain: a.items() returns a list of tuples. Adding two tuples together makes one tuple containing all elements. Thus the reduction creates one tuple containing all keys and values and then the list(...) makes a list from that.
Probably you just want this:
dictList = dict.items()
Your approach has two problems. For one you use key and value in quotes, which are strings with the letters "key" and "value", not related to the variables of that names. Also you keep adding elements to the "temporary" list and never get rid of old elements that are already in it from previous iterations. Make sure you have a new and empty temp list in each iteration and use the key and value variables:
for key, value in dict.iteritems():
temp = []
aKey = key
aValue = value
temp.append(aKey)
temp.append(aValue)
dictList.append(temp)
Also note that this could be written shorter without the temporary variables (and in Python 3 with items() instead of iteritems()):
for key, value in dict.items():
dictList.append([key, value])
If you're making a dictionary only to make a list of tuples, as creating dicts like you are may be a pain, you might look into using zip()
Its especialy useful if you've got one heading, and multiple rows. For instance if I assume that you want Olympics stats for countries:
headers = ['Capital', 'Food', 'Year']
countries = [
['London', 'Fish & Chips', '2012'],
['Beijing', 'Noodles', '2008'],
]
for olympics in countries:
print zip(headers, olympics)
gives
[('Capital', 'London'), ('Food', 'Fish & Chips'), ('Year', '2012')]
[('Capital', 'Beijing'), ('Food', 'Noodles'), ('Year', '2008')]
Don't know if thats the end goal, and my be off topic, but it could be something to keep in mind.

Categories