Reputation: 2498
I'm working on a program that requires me to loop a dictionary two keys at a time. Here's a simple representation of my dictionary.
my_dict = {
'LAP0-1': 146.48,
'LAP1-1':44.11,
'LAP2-1':25.54,
'LAP3-1':75.29,
'LAP5-2':85.76,
'LAP6-2':46.87
}
# loop dictionary 1 key at a time
for k,v in my_dict:
print k + " | " + v;
I know if I had a list, I could loop the items 2 at a time like so:
for i in range(0, len(my_list), 2):
print my_list[i] + " | " + my_list[i+1];
But is it possible to loop the dictionary two keys at a time?
I want to print out the following in a loop:
LAP0-1 | 146.48 ; LAP1-1 | 44.11
LAP1-1 | 44.11 ; LAP2-1 | 25.54
LAP2-1 | 75.29 ; LAP3-1 | 85.76
LAP5-2 | 85.76 ; LAP6-2 | 46.87
Another solution I thought of but won't for my case is this:
for i in range(0, len(my_list), 2):
print my_dict[my_list[i]] + " | " my_dict[my_list[i+1]];
where my_list[i]
is'LAP0-1'
and my_list[i+1]
is 'LAP1-1'
. It just seems inefficient having to store keep 2 data structures like that. How do I loop a dictionary two keys at a time?
Upvotes: 4
Views: 4475
Reputation: 41872
from collections import OrderedDict
from itertools import tee
my_dict = OrderedDict([
('LAP0-1', 146.48),
('LAP1-1', 44.11),
('LAP2-1', 25.54),
('LAP3-1', 75.29),
('LAP5-2', 85.76),
('LAP6-2', 46.87)
])
# pairwise() from Itertools Recipes
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
for (key1, value1), (key2, value2) in pairwise(my_dict.items()):
print("{} | {} ; {} | {}".format(key1, value1, key2, value2))
OUTPUT
LAP0-1 | 146.48 ; LAP1-1 | 44.11
LAP1-1 | 44.11 ; LAP2-1 | 25.54
LAP2-1 | 25.54 ; LAP3-1 | 75.29
LAP3-1 | 75.29 ; LAP5-2 | 85.76
LAP5-2 | 85.76 ; LAP6-2 | 46.87
Upvotes: 6
Reputation: 8202
Supplementary answer: as noted in other answers, a vanilla dictionary has no defined ordering of its keys. However, the collections
module provides OrderedDict
which does remember the order in which its keys are defined and lets you iterate over it in this order
>>> keys=("A", "nice", "sunny", "day", )
>>> d={}
>>> for key in keys: d[key]=1
...
>>> for key in d: print (key)
...
sunny
day
nice
A
>>> from collections import OrderedDict
>>> d=OrderedDict()
>>> for key in keys: d[key]=1
...
>>> for key in d: print (key)
...
A
nice
sunny
day
Upvotes: 1
Reputation: 13140
You're on the right track with your use of range()
, but you are correct in that it returns a list, which isn't very efficient if your dataset is large. You can mitigate that concern by using xrange, which returns an object that can be iterated over.
>>> my_dict = {
... 'LAP0-1': 146.48,
... 'LAP1-1':44.11,
... 'LAP2-1':25.54,
... 'LAP3-1':75.29,
... 'LAP5-2':85.76,
... 'LAP6-2':46.87
... }
>>> keys = my_dict.keys()
>>> for i in xrange(0, len(keys), 2):
... key1 = keys[i]
... key2 = keys[i+1]
... print key1, key2, my_dict[key1], my_dict[key2]
...
LAP3-1 LAP0-1 75.29 146.48
LAP5-2 LAP1-1 85.76 44.11
LAP6-2 LAP2-1 46.87 25.54
You're still creating a new list of keys, but that's probably okay.
EDIT: You should also probably be aware that dictionaries are unordered. If you want ordered dictionaries, you must use OrderedDict, which isn't as fast.
Upvotes: 2
Reputation: 2152
This will print out what you're looking for:
keys_in_order = sorted(my_dict.keys())
for i in range(len(keys_in_order) - 1):
print(keys_in_order[i] + " | " + str(my_dict[keys_in_order[i]]) + " ; " + keys_in_order[i + 1] + " | " + str(my_dict[keys_in_order[i + 1]]))
Upvotes: 1
Reputation: 113965
You can't do this with just a dictionary, as dictionaries are unsorted. However, you could get a sorted list of the keys, and go from there:
import itertools
keys = sorted(my_dict.keys(), key=lambda k:int(k.split('-')[0][3:]))
keys, ks = tee(keys)
next(ks, None)
for k1,k2 in zip(keys, ks):
print("{} | {} ; {} | {}".format(k1, my_dict[k1], k2, my_dict[k2]))
Upvotes: 2