Python for loop indexing - python

I am taking example from Mark Lutz book,Learning Python.
keys = ['spam','eggs','toast']
vals=[1,4,7]
D2={}
for (v,k) in zip(keys, vals): D2[k] = v
D2
{1: 'spam', 4: 'eggs', 7: 'toast'}
My example:
D1={}
for (k,v) in zip(keys, vals): D1[k] = v
D1
{'toast': 7, 'eggs': 4, 'spam': 1}
So,I still do not understand indexing,why is for(v,k)?

It is unpacking the key and value from each tuple of the zipped list of the keys and values list, then assigning key/value pairs . The parens are unnecessary for v, k in zip(keys, vals) will also work. The difference between yours and the book's code is the the order of v,k, you use the keys list as keys and the book does it in reverse.
You could also create the dict in one step calling dict on the zipped items, if you reverse the order of the lists passed to zip then you will get the exact same behaviour:
D2 = dict(zip(keys, vals))
print D2
D2 = dict(zip(vals, keys))
print(D2)
{'toast': 7, 'eggs': 4, 'spam': 1}
{1: 'spam', 4: 'eggs', 7: 'toast'}
The only difference is the order. The fact the lists are named keys and values is probably a bit confusing because the values end up being keys and vice versa but the main thing to understand is you are assigning k in your loop to each element from the keys list and the book code is doing the opposite.

zip will return list of tuples:
Demo:
>>> keys = ['spam','eggs','toast']
>>> vals=[1,4,7]
>>> zip(keys, vals)
[('spam', 1), ('eggs', 4), ('toast', 7)]
Unpacking
Demo:
>>> t = (1,2,3)
>>> t
(1, 2, 3)
>>> a,b,c = t
>>> a
1
>>> b
2
>>> c
3
>>> a,b = t
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
>>>
We Iterate on list, so its unpacking first item from tuple to v and second to k.
Create new key and value pair in the D2 dictionary.
Code:
>>> D2={}
>>> for (v,k) in zip(keys, vals):
... print "v:", v
... print "k", k
... D2[k] = v
... # ^ ^
# Key Value
v: spam
k 1
v: eggs
k 4
v: toast
k 7
>>> D2
{1: 'spam', 4: 'eggs', 7: 'toast'}
>>>

Related

Sort the elements in dictionary based on its values and it should allow duplicates

# Sort the elements in dictionary based on its values
# without adding duplicates
dict1 = **{1:1, 2:9, 3:4, 4:6}**
sorted_values = sorted(dict1.values()) # Sort the values
sorted_dict = {}
for i in sorted_values:
for k in dict1.keys():
if dict1[k] == i:
sorted_dict[k] = dict1[k]
break
print(sorted_dict)
Output : **{1: 1, 3: 4, 4: 6, 2: 9}**
# with adding duplicates
# Sort the elements in dictionary based on its values
dict1 = **{0:6, 1:1, 2:9, 3:4, 4:6}**
sorted_values = sorted(dict1.values()) # Sort the values
sorted_dict = {}
for i in sorted_values:
for k in dict1.keys():
if dict1[k] == i:
sorted_dict[k] = dict1[k]
break
print(sorted_dict)
Output :
{1: 1, 3: 4, 0: 6, 2: 9}
here 4:6 is not printing
I have to print all values from dictionary even there are duplicates in a dictionary
What you do is terribly inefficient because you use 2 nested loops: an outer one on the values, then an inner one on the keys of the whole dictionary. It would be both simpler and most efficient to directly process the dictionary items and sort them according to the value:
sorted_items = sorted(dict1.items(), key=lambda x: x[1])
sorted_dict = dict(sorted_items)
with you 2nd example, it gives as expected:
{1: 1, 3: 4, 0: 6, 4: 6, 2: 9}
You can consider using an ordered dict for this.
>>> import operator
>>> from collections import OrderedDict
>>> dict1 = {1:1, 2:9, 3:4, 4:6}
>>> sorted_dict1 = sorted(dict1.items(), key=operator.itemgetter(1))
>>> dict2 = (OrderedDict(sorted_dict1))
>>> print(dict2)
OrderedDict([(1, 1), (3, 4), (4, 6), (2, 9)])
However, to have order and duplicates at the same time, tuples are a better solution.

deconstructing and reconstructing python dictionary

I have a dictionary which I need to deconstruct its keys and values in perhaps two lists(or any other type that does the job) and later in another function, construct the exact same dictionary putting back the keys and values. What's the right way of approaching this?
You can use dict.items() to get all the key-value pairs from the dictionary, then either store them directly...
>>> d = {"foo": 42, "bar": 23}
>>> items = list(d.items())
>>> dict(items)
{'bar': 23, 'foo': 42}
... or distribute them to two separate lists, using zip:
>>> keys, values = zip(*d.items())
>>> dict(zip(keys, values))
{'bar': 23, 'foo': 42}
d = {'jack': 4098, 'sape': 4139}
k, v = d.keys(), d.values()
# Do stuff with keys and values
# -
# Create new dict from keys and values
nd = dict(zip(k, v))
Better Don't deconstruct it. Where you need the keys and values as list you can get that with the following methods.
keyList=list(dict.keys())
valueList = [dict[key] for key in keyList] or [dict[key] for key in dict.keys()]
Hope it helps.
To deconstruct a Dict to two list
>>> test_dict={"a":1, "b":2}
>>> keyList=[]
>>> valueList =[]
>>> for key,val in test_dict.items():
... keyList.append(key)
... valueList.append(val)
>>> print valueList
[1, 2]
>>> print keyList
['a', 'b']
To construct from two list of key and value I would use zip method along with dict comprehension.
>>> {key:val for key,val in zip(keyList,valueList)}
{'a': 1, 'b': 2}

How to iterate over a dynamic object?

I have some code that iterates over the values of a dictionary. If the value meets certain conditions, it is deleted from the dictionary. Those conditions are contingent on the existence of other values in the dictionary. This is why I don't want to just copy the old dictionary and make deletions, then re-attribute it.
When I try to run it, I get an error that the size of the dictionary changed while iterating it.
Is there a way to iterate over a dictionary that allows it to change size, and the existence of keys and values, while it is iterating?
Build a new dictionary which contains the keys you want to keep. This can be done with a dictionary comprehension, or a manual for loop.
Here's a comprehension:
return {k: v for k, v in my_dict.items() if some-condition}
Here's a manual loop:
result = {}
for k, v in my_dict.items():
if some-condition:
result[k] = v
return result
Well, yes you can iterate on by the keys (Python3)! Take a look:
>>> dc
{1: 'aze', 3: 'poi', 4: 'mlk'}
>>> dc = {1:"aze", 2:"qsd", 3:"poi", 4:"mlk"}
>>> dc
{1: 'aze', 2: 'qsd', 3: 'poi', 4: 'mlk'}
>>> keys = list(dc.keys())
>>> keys
[1, 2, 3, 4]
>>> for k in keys:
if "q" in dc[k]:
del dc[k]
>>> dc
{1: 'aze', 3: 'poi', 4: 'mlk'}
>>>
You can iterate over the keys instead of over the dict itself. In the following example, all values that are odd-numbered are removed from the dict:
>>> a = {'a': 12, 'b': 3, 'c': 14}
>>> for key in list(a.keys()):
if a[key] % 2 == 0:
del a[key]
>>> a
{'b': 3}

Python - Opposite of dictionary search [duplicate]

This question already has answers here:
Inverse dictionary lookup in Python
(13 answers)
Closed 7 years ago.
>>>Dictionary[key]
The above statement returns the first corresponding value of the 'key' from the 'Dictionary' but is there a function that does the opposite, i.e. search for the key by it's value
You can write simple lambda for this:
d={"a":5, "bf": 55, "asf": 55}
search_key = lambda in_d, val: (k for k,v in in_d.items() if v == val)
for k in search_key(d, 55):
print(k)
# since the lambda returns generator expression you can simply print
# the keys as follows:
print(list(search_key(d, 55)))
# or get the key list
key_list = list(search_key(d, 55))
Gives:
asf
bf
Just iterate over the dictionary items and check for the value with your string. If it matches then print it's corresponding key.
>>> d = {'foo':1,'bar':2}
>>> for k,v in d.items():
if v == 1:
print(k)
foo
There's no single function, but it's easy to get the (possibly multiple) keys for a particular value:
>>> d = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 0, 'g': 1}
>>> [k for k, v in d.items() if v == 1]
['b', 'g']
i don't think you can, but you can do this
In [3]: dict_1 = {1:"one", 2:"two"}
In [4]: for number, alphabet in dict_1.items():
...: if alphabet == "two":
...: print number
...:
Trivial, using list comprehensions:
>>> d = {'a': 1, 'b': 2, 'c': 1}
>>> l = [k for k, v in d.items() if v == 1]
>>> l
['c', 'a']
For this you can work with .keys() and .values(), which will return a list of keys or values respectivley. These lists can be easily iterated over and searched.
An example with a simple dictionary:
>>> D1 = {'A':1, 'B':2, 'C':1}
>>> D1['A']
1
>>> for key in D1.keys():
if D1[key] == 1:
print(key)
C
A
As Padraic Cunningham pointed out, a key must be unique, but a value does not, so you run into problems when you have multiple keys that match 1 value.
Perhaps it's too straightforward...
def val2key(dict, val):
for k, v in dict.items():
if v == val:
return k
return None
Use a list comprehension and substitute the name of your dictionary and the desired value.
keys = [k for k, v in my_dict.items() if v == my_value]

Python: Iterate alphabetically over OrderedDict

In a script I have an OrderedDict groups that gets fed key/value pairs alphabetically.
In another part of the script, I'm checking against files that have the same same as key like so:
for (key, value) in groups.items():
file = open(key, 'r')
# do stuff
Stuff happens just fine, part of which is printing a status line for each file, but how can I get Python to iterate through groups alphabetically, or at least numerically as they are ordered (since they are being entered in alphabetical order anyways)?
The whole point of an OrderedDict is that you can iterate through it normally in the order that keys were entered:
>>> from collections import OrderedDict
>>> d = OrderedDict()
>>> d[1] = 2
>>> d[0] = 3
>>> d[9] = 2
>>> for k, v in d.items():
print(k, v)
(1, 2)
(0, 3)
(9, 2)
Just make sure you don't feed OrderedDict(...) a dictionary to initialize it or it starts off unordered.
If all you want to do is iterate through a dictionary in order of the keys, you can use a regular dictionary and sorted():
>>> d = dict(s=5,g=4,a=6,j=10)
>>> d
{'g': 4, 's': 5, 'j': 10, 'a': 6}
>>> for k in sorted(d):
print(k, ':', d[k])
a : 6
g : 4
j : 10
s : 5
>>>
(pardon the python3 print())
If you really want to stick with the ordered dict, then read the documentation which shows an example of reordering an OrderedDict:
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
If you really entered them into an OrderedDict alphabetically in the first place, then I'm not sure why you're having trouble.

Categories