How can loop over two dictionaries at once? - python

How can I iterate through items of two dictionaries in a single loop? This is not working:
for word, cls in self.spam.items() and self.ham.items():
pass

Use itertools.chain:
from itertools import chain
for word, cls in chain(self.spam.items(), self.ham.items()):
print(word, cls)

Since in Python2, dict.items() will generate a list of (key,value) tuples, you can concatenate the two lists, whereas in Python3, it will return a viewing object, hence we need to convert it to a list, so the following is also one way to do:
>>> d1 = {1:'ONE',2:'TWO'}
>>> d2 = {3:'THREE', 4:'FOUR'}
>>> dict_chained = d1.items() + d2.items() #Python2
>>> dict_chained = list(d1.items())+list(d2.items())) #Python3
>>> for x,y in dict_chained:
print x,y
1 ONE
2 TWO
3 THREE
4 FOUR
>>>

Related

Dictionary of pair in python

I am new to python and was trying to make a dict of pairs in python.
What I would have done in c++ is
dist[make_pair(a,b)]=1
I am not sure how I can do the same in python
Edit
What I basically want to do is to map a pair of two integers to some value-
for example-
(1,2) -> 1
(1,3) -> 2
(2,1) ->3
I want to map pairs to some integer value
You can use the data structure "tuple" as a key in the dictionary. If you want to define a function that returns a n-tuple given n inputs, you can do that also.
a = 4
b = 5
dict_example = dict()
dict_example[(a,b)] = 1
print dict_example[(a,b)]
This prints the value of key (a,b), which is 1
To create an element having the tuple (a,b) as key, and 1 as a value, you just have to do :
new_dict = {(a,b) : 1}
If such a dict already exist, and you want to add the pair a,b as a key and 1 as a value, you have to do :
existing_dict[(a,b)] = 1
You can also use existing_dict[a,b] = 1 as Duncan pointed out.
I guess you tried using an array as a dict key, like:
>>> d = {}
>>> pair = [0, 1]
>>> d[pair] = 'foo'
TypeError: unhashable type: 'list'
Ok, what is that? Python dict keys must not be mutable. They can be numbers, strings and other hashable types - you can't use mutable types like lists, dicts and other mutable collections.
There is a collection that is very like a list but is not mutable: the tuple.
>>> d[tuple(pair)] = 'foo'
>>> d
{(1, 2): 'foo'}
As you can see, the literal for a tuple is (v1, v2, ..., vN). In places where it is not ambiguous, you can even omit the parenthesis:
>>> pair = 0, 1
>>> pair
(0, 1)
More than once I was bit by this when I left a trailing comma while refactoring code:
>>> x = 1, # I meant x = 1
>>> x
(1,)
That is the literal for a tuple with just 1 element.

Converting each element of a list to tuple

to convert each element of list to tuple like following :
l = ['abc','xyz','test']
convert to tuple list:
newl = [('abc',),('xyz',),('test',)]
Actually I have dict with keys like this so for searching purpose I need to have these.
You can use a list comprehension:
>>> l = ['abc','xyz','test']
>>> [(x,) for x in l]
[('abc',), ('xyz',), ('test',)]
>>>
Or, if you are on Python 2.x, you could just use zip:
>>> # Python 2.x interpreter
>>> l = ['abc','xyz','test']
>>> zip(l)
[('abc',), ('xyz',), ('test',)]
>>>
However, the previous solution will not work in Python 3.x because zip now returns a zip object. Instead, you would need to explicitly make the results a list by placing them in list:
>>> # Python 3.x interpreter
>>> l = ['abc','xyz','test']
>>> zip(l)
<zip object at 0x020A3170>
>>> list(zip(l))
[('abc',), ('xyz',), ('test',)]
>>>
I personally prefer the list comprehension over this last solution though.
Just do this:
newl = [(i, ) for i in l]

Is there any single function to print an iterable's values?

Suppose I have an iterable:
var = "ABCDEF"
I get the iterable like this:
it = itertools.combinations(var,2)
Is there any single function to print all values of iterables like
printall(it)
rather than using the for loop?
This rather depends what you want, if you want to print out all the values, you need to compute them - an iterable doesn't guarantee the values are computed until after they are all requested, so the easiest way to achieve this is to make a list:
print(list(iterable))
This will print out the items in the normal list format, which may be suitable. If you want each item on a new line, the best option is, as you mentioned, a simple for loop:
for item in iterable:
print(item)
If you don't need the data in a specific format, but just need it to be readable (not all on one line, for example), you may want to check out the pprint module.
A final option, which I don't really feel is optimal, but mention for completeness, is possible in 3.x, where the print() function is very flexible:
print(*iterable, sep="\n")
Here we unpack the iterable as the arguments to print() and then make the separator a newline (as opposed to the usual space).
You could use the str.join method and join each element of the iterable on a new line.
print('\n'.join(it))
You can use format which will allow each element to be formated as you please:
>>> print '\n'.join('{:>10}'.format(e) for e in iter([1,2,'1','2',{1:'1'}]))
1
2
1
2
{1: '1'}
Each element does not need to be a string necessarily, but must have a __repr__ method if it is not a string.
You can then easily write the function you desire:
>>> def printall(it,w): print '\n'.join('{:>{w}}'.format(e,w=w) for e in it)
>>> printall([1,2,'3','4',{5:'6'}],10)
1
2
3
4
{5: '6'}
I am using a list, but any iterable would do.
You can use chain() function from itertools to create iterator for var data and then just unpack using * operator of iterator
>>> from itertools import chain
>>> var = 'ABCDEF'
>>> print(*chain(var))
A B C D E F
>>> print(*chain(var), sep='\n')
A
B
C
D
E
F
If you just need to iterate over existing data and print it out again you can use star operator * for this
>>> print(*var)
A B C D E F
>>> print(*var, sep='\n')
A
B
C
D
E
F
If you insist on a solution which iterates without a for loop and works for infinite iterators:
from more_itertools import consume
def printall(it):
consume(map(print, it))
Instead of the for loop we have consume here.
Note that in this case the iterator is consumed while printing.
This, of course, works for infinite iterators as well:
from itertools import count
printall(count())
Just for fun. :)

Python map() dictionary values

I'm trying to use map() on the dict_values object returned by the values() function on a dictionary. However, I can't seem to be able to map() over a dict_values:
map(print, h.values())
Out[31]: <builtins.map at 0x1ce1290>
I'm sure there's an easy way to do this. What I'm actually trying to do is create a set() of all the Counter keys in a dictionary of Counters, doing something like this:
# counters is a dict with Counters as values
whole_set = set()
map(lambda x: whole_set.update(set(x)), counters.values())
Is there a better way to do this in Python?
In Python 3, map returns an iterator, not a list. You still have to iterate over it, either by calling list on it explicitly, or by putting it in a for loop. But you shouldn't use map this way anyway. map is really for collecting return values into an iterable or sequence. Since neither print nor set.update returns a value, using map in this case isn't idiomatic.
Your goal is to put all the keys in all the counters in counters into a single set. One way to do that is to use a nested generator expression:
s = set(key for counter in counters.values() for key in counter)
There's also the lovely dict comprehension syntax, which is available in Python 2.7 and higher (thanks Lattyware!) and can generate sets as well as dictionaries:
s = {key for counter in counters.values() for key in counter}
These are both roughly equivalent to the following:
s = set()
for counter in counters.values():
for key in counter:
s.add(key)
You want the set-union of all the values of counters? I.e.,
counters[1].union(counters[2]).union(...).union(counters[n])
? That's just functools.reduce:
import functools
s = functools.reduce(set.union, counters.values())
If counters.values() aren't already sets (e.g., if they're lists), then you should turn them into sets first. You can do it using a dict comprehension using iteritems, which is a little clunky:
>>> counters = {1:[1,2,3], 2:[4], 3:[5,6]}
>>> counters = {k:set(v) for (k,v) in counters.iteritems()}
>>> print counters
{1: set([1, 2, 3]), 2: set([4]), 3: set([5, 6])}
or of course you can do it inline, since you don't care about counters.keys():
>>> counters = {1:[1,2,3], 2:[4], 3:[5,6]}
>>> functools.reduce(set.union, [set(v) for v in counters.values()])
set([1, 2, 3, 4, 5, 6])

Python dictionary creation error

I am trying to create a Python dictionary from a stored list. This first method works
>>> myList = []
>>> myList.append('Prop1')
>>> myList.append('Prop2')
>>> myDict = dict([myList])
However, the following method does not work
>>> myList2 = ['Prop1','Prop2','Prop3','Prop4']
>>> myDict2 = dict([myList2])
ValueError: dictionary update sequence element #0 has length 3; 2 is required
So I am wondering why the first method using append works but the second method doesn't work? Is there a difference between myList and myList2?
Edit
Checked again myList2 actually has more than two elements. Updated second example to reflect this.
You're doing it wrong.
The dict() constructor doesn't take a list of items (much less a list containing a single list of items), it takes an iterable of 2-element iterables. So if you changed your code to be:
myList = []
myList.append(["mykey1", "myvalue1"])
myList.append(["mykey2", "myvalue2"])
myDict = dict(myList)
Then you would get what you expect:
>>> myDict
{'mykey2': 'myvalue2', 'mykey1': 'myvalue1'}
The reason that this works:
myDict = dict([['prop1', 'prop2']])
{'prop1': 'prop2'}
Is because it's interpreting it as a list which contains one element which is a list which contains two elements.
Essentially, the dict constructor takes its first argument and executes code similar to this:
for key, value in myList:
print key, "=", value

Categories