简体   繁体   English

Python字典中的随机随机键和值

[英]Randomly Shuffle Keys and Values in Python DIctionary

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. 我已经找到random.sample,但我想知道是否有更Pythonic /更快的方法来做到这一点。

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

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

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: 请注意,尽管使用random.sample方式更为实用,但是使用random.shuffle的速度更快:

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

sorry the only way to make it faster is by using numpy :/. 抱歉,提高速度的唯一方法是使用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. 无论您做什么,都必须以某种方式加扰所有索引,而这需要时间-因此在C中进行操作会有所帮助。 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' 不幸的是,除非它很小,否则复制通常很慢-并且如果不占用额外的行,就无法传递指针/引用-尽管我在争论这是否使其成为“非Python的”

namely if you look at the Zen of Python or just do import this in a python session one of the lines is: 也就是说,如果您查看PythonZen或只是将其import this python会话中,则以下行之一是:

Although practicality beats purity. 尽管实用性胜过纯度。

so it's open to interpretation of course :) 所以对解释当然是开放的:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM