Randomly Shuffle Keys and Values in Python DIctionary

匿名 (未验证) 提交于 2019-12-03 09:52:54

问题:

Is there a way to randomly shuffle what keys correspond to what values? I have found random.sample but I was wondering if there was a more pythonic/faster way of doing this.

Example: a = {"one":1,"two":2,"three":3}

Shuffled: a_shuffled = {"one":2,"two":3,"three":1}

回答1:

sorry the only way to make it faster is by using numpy :/. No matter what you do it has to somehow scramble all the indices which takes time - so doing it in C will help slightly. Also the difference between sheer random and this random is that you can't have repeated indices.

sorry it's sort of long now - so you'll have to do some scrolling

E.g.                                                                                                                                                 # made for python 2.7 but should be able to work in python 3 import random import numpy as np from time import time   def given_seq(): #general example     start = time()     a = {"one":1,"two":2,"three":3}     keys = a.keys()     random.shuffle(keys)     a = dict(zip(keys, a.values()))  #Large example  a = dict(zip(range(0,100000), range(1,100001)))  def random_shuffle():     keys = a.keys()     random.shuffle(keys)     b = dict(zip(keys, a.values()))  def np_random_shuffle():     keys = a.keys()     np.random.shuffle(keys)     b = dict(zip(keys, a.values()))  def np_random_permutation():     #more concise and using numpy's permutation option     b = dict(zip(np.random.permutation(a.keys()), a.values()))  #if you precompute the array key as a numpy array  def np_random_keys_choice():     akeys = np.array(a.keys())     return dict(zip(akeys[np.random.permutation(len(akeys))],a.values()))  def np_random_keys_shuffle():     key_indexes = np.arange(len(a.keys()))     np.random.shuffle(key_indexes)     return dict(zip(np.array(a.keys())[key_indexes],a.values()))  #fixed dictionary size key_indexes = np.arange(len(a.keys())) def np_random_fixed_keys_shuffle():     np.random.shuffle(key_indexes)     return dict(zip(np.array(a.keys())[key_indexes],a.values()))   #so dstack actually slows things down def np_random_shuffle_dstack():     keys = a.keys()     np.random.shuffle(keys)     return dict(np.dstack((keys, a.values()))[0])  if __name__=='__main__':     import timeit     # i can use global namespace level introspection to automate the below line but it's not needed yet     for func in ['given_seq', 'random_shuffle', 'np_random_shuffle', 'np_random_permutation', 'np_random_keys_choice',             'np_random_keys_shuffle', 'np_random_fixed_keys_shuffle']:         print func, timeit.timeit("{}()".format(func), setup = "from __main__ import {}".format(''.join(func)), number = 200) 
given_seq 0.00103783607483 random_shuffle 23.869166851 np_random_shuffle 16.3060112 np_random_permutation 21.9921720028 np_random_keys_choice 21.8105020523 np_random_keys_shuffle 22.4905178547 np_random_fixed_keys_shuffle 21.8256559372 

Using Choice/Permutation may look nicer - but it's not faster by any means. Unfortunately copying is usually slow unless it's a small size - and there's no way to pass pointers/references without it having to take up an extra line - though I debate if this makes it 'non-pythonic'

namely if you look at the Zen of Python or just do import this in a python session one of the lines is:

Although practicality beats purity.

so it's open to interpretation of course :)



回答2:

In [47]: import random  In [48]: keys = a.keys()  In [49]: values = a.values()  In [50]: random.shuffle(values)  In [51]: a_shuffled = dict(zip(keys, values))  In [52]: a_shuffled Out[52]: {'one': 2, 'three': 1, 'two': 3} 

Or, more pithy would be:

In [56]: dict(zip(a.keys(), random.sample(a.values(), len(a)))) Out[56]: {'one': 3, 'three': 2, 'two': 1} 

(but I suppose that is the solution you already came up with.)


Note that although using random.sample is pithier, using random.shuffle is a bit faster:

import random import string def using_shuffle(a):     keys = a.keys()     values = a.values()     random.shuffle(values)     return dict(zip(keys, values))  def using_sample(a):     return dict(zip(a.keys(), random.sample(a.values(), len(a))))  N = 10000 keys = [''.join(random.choice(string.letters) for j in range(4)) for i in xrange(N)] a = dict(zip(keys, range(N)))  In [71]: %timeit using_shuffle(a) 100 loops, best of 3: 5.14 ms per loop  In [72]: %timeit using_sample(a) 100 loops, best of 3: 5.78 ms per loop 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!