2

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?

cooldood3490
  • 2,418
  • 7
  • 51
  • 66
  • for skip every k element http://stackoverflow.com/questions/1403674/pythonic-way-to-return-list-of-every-nth-item-in-a-larger-list – Andres May 03 '16 at 17:46
  • 3
    Are you expecting the dict to remember what order you wrote the entries in? Dicts are semantically unordered; they're key-value lookup structures. Iterating over them may produce an entirely different order from the order you wrote. If what you really want is a sequence of ordered pairs, a list of tuples is frequently a better data structure. – user2357112 May 03 '16 at 17:46

5 Answers5

5
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
cdlane
  • 40,441
  • 5
  • 32
  • 81
2

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]))
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
2

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.

Ken Kinder
  • 12,654
  • 6
  • 50
  • 70
1

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]]))
gr1zzly be4r
  • 2,072
  • 1
  • 18
  • 33
1

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
nigel222
  • 7,582
  • 1
  • 14
  • 22