cooldood3490
cooldood3490

Reputation: 2498

Python: Loop Dictionary, Two keys at a time

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

Answers (5)

cdlane
cdlane

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

nigel222
nigel222

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

Ken Kinder
Ken Kinder

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

gr1zzly be4r
gr1zzly be4r

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

inspectorG4dget
inspectorG4dget

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

Related Questions