0

It is easier to explain with an example to make my question clearer:

For example:

example_dict = {1 : "A", 2 : "B", 3 : "C", 4 : "D", 5 : "E"}

Imagining that I want to start my iteration on key 3 in order to get the corresponding values ​​until iterating to it again.

# Chosen the key = 3 will return:
["C","D","E","A","B"]

So what is the best way to iterate from a key to itself?

Is the iteration supposed to reach the end of the dictionary and go back to iterating from the beginning until it finds the key chosen initially?

Another example:

example_dict = {23 : "Hello", 3 : "Bye", 11 : "Shame", 45 : "Nice", 2 : "Pretty"}

# Chosen the key = 3 will return:
["Bye","Shame","Nice","Pretty","Hello"]
João Santos
  • 194
  • 11

4 Answers4

2

An approach using itertools:

You actually want to do it by key, so just find the "index" of the key first and use that (the index of the list created from the keys, to be precise). Use cycle and islice from itertools to create an iterator over the values, using the position of the key and the size of the dictionary:

>>> idx = list(example_dict).index(3)
>>> list(islice(cycle(example_dict.values()), idx, idx + len(example_dict)))
['C', 'D', 'E', 'A', 'B']
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
1

You can use dict.values then use slicing on the list:

val_list = list(example_dict.values())
output = val_list[2:] + val_list[:2]

['C', 'D', 'E', 'A', 'B']

And to find the index of 3 turn the dict into a list and use list.index:

>>> list(example_dict).index(3)
2
Jab
  • 26,853
  • 21
  • 75
  • 114
1

This is not normal though you can use your ownn function to achieve this

def get_elements(dictionary, key):
    l = list(dictionary.items())
    for i in range(len(l)):
        if(l[i][0] == key): # check if this the required key
            return[e[1] for e in  l[i:] + l[0:i]]

Output

d = {1 : "A", 2 : "B", 3 : "C", 4 : "D", 5 : "E"}

get_elements(d, 3)

['C', 'D', 'E', 'A', 'B']
Epsi95
  • 8,832
  • 1
  • 16
  • 34
0

You can combine a couple of functions from itertools to do it in a list comprehension with iterators only and no intermediate list created:

from itertools import dropwhile,takewhile

d = {1 : "A", 2 : "B", 3 : "C", 4 : "D", 5 : "E"}
K = 3

r = (v for f in (dropwhile,takewhile) for _,v in f(lambda k:k[0]!=K,d.items()))

print(type(r))  # <class 'generator'>
print(*r)       # C D E A B

The way this works is by using dropwhile to get the values from the specified key (K) up to the end and then using takewhile to get the values that precede the key. Because the two functions have the same signature and apply the same condition, they can be part of the list comprehension as a first level that selects a function to apply to the dictionary.

This approach produces a generator. If you need a list you can enclose the comprehension between square brackets instead of parentheses.

d = {23 : "Hello", 3 : "Bye", 11 : "Shame", 45 : "Nice", 2 : "Pretty"}
K = 3

r = [v for f in (dropwhile,takewhile) for _,v in f(lambda k:k[0]!=K,d.items())]

print(r) # ['Bye', 'Shame', 'Nice', 'Pretty', 'Hello']

It is also possible to do it without any library module by creating a list of keys to find the position of the starting key and iterating in a subrange of the doubled up dictionary:

r = [d[k] for i,k in enumerate((*d,*d),-[*d].index(key)) if i in range(len(d))]
Alain T.
  • 40,517
  • 4
  • 31
  • 51