1
\$\begingroup\$

I wrote this function today that shift the values of a dictionnary:

def shift_dict(dic, shift):
 # Save the dic length
 dic_len = len(dic)
 # Reduce the shift to the dic length
 shift = shift % dic_len
 # convert the dict to a tupple to reference by index
 list_dic = [(k,v) for k, v in dic.iteritems()]
 # Create the new shifted dict
 shifted = {
 list_dic[x][0]: list_dic[ (x - shift) % dic_len ][1]
 for x in xrange(dic_len)
 }
 return shifted

The idea is to keep the keys but to assign the nth - shift value to it.

A few examples:

dic = {
 'a':10,
 'b':2,
 'c':30,
 'd':4,
 'e':50,
 'f':6,
}
print dic
print shift_dict(dic, 1)
print shift_dict(dic, 4)
print shift_dict(dic, -2)

Result:

{'a': 10, 'c': 30, 'b': 2, 'e': 50, 'd': 4, 'f': 6}
{'a': 6, 'c': 10, 'b': 30, 'e': 2, 'd': 50, 'f': 4}
{'a': 2, 'c': 50, 'b': 4, 'e': 6, 'd': 10, 'f': 30}
{'a': 30, 'c': 2, 'b': 50, 'e': 4, 'd': 6, 'f': 10}

I find that the "create a list and then another dictionnary" is not very effective, but I couldn't think of another way to do it.

Any thoughts?

asked May 14, 2017 at 14:57
\$\endgroup\$
7
  • 2
    \$\begingroup\$ The result depends on the arbitrary ordering of the dict; I'm getting a different result. Seems kind of pointless to me, I'm afraid. \$\endgroup\$ Commented May 14, 2017 at 16:38
  • \$\begingroup\$ First of all as @JanneKarila said if you want ordered dict you should use OrderedDict. Second this can be done much more simply. \$\endgroup\$ Commented May 14, 2017 at 16:59
  • \$\begingroup\$ I noticed the ordering after this, thanks for the comment. user1685095: what do you mean, can the OrderedDict simplify this? \$\endgroup\$ Commented May 14, 2017 at 17:01
  • \$\begingroup\$ See my answer, please. \$\endgroup\$ Commented May 14, 2017 at 17:04
  • \$\begingroup\$ Are you using 3.6, as it'd explain why the dictionary is ordered. However you shouldn't rely on this functionality. \$\endgroup\$ Commented May 14, 2017 at 17:15

1 Answer 1

4
\$\begingroup\$

Use OrderedDict if you want an ordered dictionary.

from collections import OrderedDict
from itertools import islice, cycle
def shift_dict(dct, shift):
 shift %= len(dct)
 return OrderedDict(
 (k, v)
 for k, v in zip(dct.keys(), islice(cycle(dct.values()), shift, None))
 )
Graipher
41.6k7 gold badges70 silver badges134 bronze badges
answered May 14, 2017 at 17:03
\$\endgroup\$
2
  • \$\begingroup\$ Sorry but I've just spotted that my example was pretty bad thus, this solution does not work, I'm updating the question. \$\endgroup\$ Commented May 14, 2017 at 17:52
  • \$\begingroup\$ @nobe4 Okay, I'll try to help \$\endgroup\$ Commented May 14, 2017 at 17:53

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.