什么是从列表中popup一个随机元素最pythonic的方式?
说我有一个列表x
与未知的长度,我想从中随机popup一个元素,以便列表中不包含元素之后。 什么是最pythonic这样做呢?
我可以使用pop
, random.randint
和len
一个非常不方便的combincation来做,并希望看到更短或更好的解决scheme:
import random x = [1,2,3,4,5,6] x.pop(random.randint(0,len(x)-1))
编辑:我想实现的是从列表中连续popup随机元素。 (即随机popup一个元素并将其移动到字典中,随机popup另一个元素并将其移动到另一个字典中…)
请注意,我正在使用Python 2.6,并没有通过searchfunctionfind任何解决scheme。
你看起来要达到什么样的程度,首先看起来并不是Pythonic。 你不应该从列表中间删除东西,因为在我所知的所有Python实现中,列表被实现为数组,所以这是一个O(n)
操作。
如果你真的需要这个function作为algorithm的一部分,你应该检查一个数据结构,如支持从中间高效删除的blist
。
在纯Python中,如果你不需要访问剩余的元素,你可以做什么只是先清单,然后遍历它:
lst = [1,2,3] random.shuffle(lst) for x in lst: # ...
如果你真的需要余数(这是一个代码味道,恕我直言),至less你可以从列表的末尾(这是快!) pop()
):
while lst: x = lst.pop() # do something with the element
一般来说,如果你使用更多的function风格,而不是变异的状态(就像你对列表做的那样),你可以更加优雅地expression你的程序。
你不会比这更好,但是这是一个小小的改进:
x.pop(random.randrange(len(x)))
random.randrange()
上的文档:
random.randrange([start],stop [,step])
从range(start, stop, step)
返回一个随机select的元素。 这相当于choice(range(start, stop, step))
,但实际上并不构build范围对象。
这里有另外一个select:为什么不先洗牌,然后开始popup它的元素,直到没有更多的元素保留下来? 喜欢这个:
import random x = [1,2,3,4,5,6] random.shuffle(x) while x: p = x.pop() # do your stuff with p
从列表中删除一个随机索引的单个元素,如果其余列表元素的顺序不重要:
import random L = [1,2,3,4,5,6] i = random.randrange(len(L)) # get random index L[i], L[-1] = L[-1], L[i] # swap with the last element x = L.pop() # pop last element O(1)
交换用于避免从列表中间删除O(n)行为。
一种方法是:
x.remove(random.choice(x))
虽然没有从列表中popup,但我在Google上遇到了这个问题,同时尝试从列表中获取X个随机项目而没有重复。 这是我最终使用的:
items = [1, 2, 3, 4, 5] items_needed = 2 from random import shuffle shuffle(items) for item in items[:items_needed]: print(item)
这可能会稍微低效,因为你正在洗牌整个列表,但只使用它的一小部分,但我不是一个优化专家,所以我可能是错的。
这个答案来自@ niklas-b :
“ 你可能想使用像pypi.python.org/pypi/blist ”
引用PYPI页面 :
…类似于列表types,在小列表上具有更好的渐进性能和类似的性能
blist是Python列表的替代品,可以在修改大型列表时提供更好的性能。 blist包还提供了sorting列表,sorting集,弱sorting列表,弱sorting列表,sorting列表和二元types。
人们会认为随机访问/随机运行结束时性能降低 ,因为它是“写入时复制”数据结构。 这违反了Python列表中的许多用例假设, 因此请谨慎使用它 。
然而,如果你的主要用例是用一个列表来做一些奇怪和不自然的事情(如@OP给出的强制性例子,或者我的Python 2.6先入先出队列传递问题),那么这将很好地适应账单。
我知道这是一个古老的问题,但仅仅为了文档的缘故:
如果你(用Googlesearch同一个问题的人)正在做我认为你正在做的事情,那就是从列表中随机selectk个项目(其中k <= len(yourlist)),但要确保每个项目都不会被选中。比一次(=没有replace的采样),你可以使用@ jf-sebastianbuild议的random.sample 。 但是不知道更多关于用例,我不知道这是否是你需要的。