2

Python 3.6.x

I've got a defaultdict, which is named xref_to_records. It has got strings as keys, and lists as values.

for k, v in xref_to_records.items():
    print(type(k))
    print(type(xref_to_records[k]))
    break

It produces:

<class 'str'>
<class 'list'>

What I'm trying to do is to iterate through its items to compare the values list of a key against the next one. I know this question was probably already answered somewhere, but I couldn't figure to make work any of the provided approaches.

I've tried to iterate through the lenght of keys, but it doesn't work.

keys = xref_to_records.keys()
    for i in range(len(keys)):
    this_key = keys[i]

It raises me a TypeError:

TypeError: 'dict_keys' object does not support indexing

I've tried also to iterate through keys using next() but unsuccessfully.

frick = None
for k,v in iter(xref_to_records.items()):
    if k != frick:
        res = next(k, None)
        print(res)
    break

Again a TypeError :

TypeError: 'str' object is not an iterator

Expected output

for k, v in xref_to_records.items():
     somefunctions(k)
     somefunctions(next(k))
Shred
  • 358
  • 2
  • 15

2 Answers2

2

Strictly speaking, a dictionary does not have a specific order. However, in never versions of Python, the items in a dict should be iterated in the original order of insertion, and since defaultdict is a subclass of dict, the same should hold there, too.

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for i in range(4): d[i] = list(range(i+1))
>>> d[10] = []
>>> d[4] = []
>>> d
defaultdict(list, {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [], 10: []})
>>> list(d)
[0, 1, 2, 3, 10, 4]

You can then get two iter of the dictionary, advance one of those once using next, and zip them to get pairs of (current, next) elements. (Here, it's just pairs of the keys, but of course you can just get the corresponding values from the dictionary.)

>>> from itertools import tee
>>> it1, it2 = tee(iter(d))
>>> next(it2)
>>> for a, b in zip(it1, it2):
...     print(a, b)
...
0 1
1 2
2 3
3 10
10 4

For older versions of Python, you might have to use a collections.OrderedDict instead. If, instead, you do not want insertion order but e.g. lexicographic ordering, you can just get the iter from the sorted keys.

tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • This is a good answer because of the good example of zip but in my case for loop stops before expected printing just the first two keys (3 total). – Shred Aug 31 '20 at 09:43
1

see below

from collections import defaultdict
xref_to_records = defaultdict(list)

xref_to_records['A'].append(9)
xref_to_records['A'].append(12)
xref_to_records['B'].append(99)
xref_to_records['B'].append(112)
xref_to_records['C'].append(99.34)
xref_to_records['C'].append(112.88)
xref_to_records['C'].append(4112.88)

keys = list(xref_to_records.keys())
for idx,key in enumerate(keys):
    if idx > 0:
        print('compare:')
        print('current:' + str(xref_to_records[key]))
        print('previous: ' + str(xref_to_records[keys[idx-1]]))
        print('')
    

output

compare:
current:[99, 112]
previous: [9, 12]

compare:
current:[99.34, 112.88, 4112.88]
previous: [99, 112]
balderman
  • 22,927
  • 7
  • 34
  • 52
  • Simple approach, no additional module.. So I was just forgetting to put keys into a list in order to enumerate them. It works – Shred Aug 31 '20 at 09:46