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?

\$\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\$ May 14 '17 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\$ May 14 '17 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\$
    – nobe4
    May 14 '17 at 17:01
  • \$\begingroup\$ See my answer, please. \$\endgroup\$ May 14 '17 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\$
    – Peilonrayz
    May 14 '17 at 17:15
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))
    )
\$\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\$
    – nobe4
    May 14 '17 at 17:52
  • \$\begingroup\$ @nobe4 Okay, I'll try to help \$\endgroup\$ May 14 '17 at 17:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.