从字典中随机删除项目

6
如何在Python中从字典中随机删除项?
我需要从字典中删除指定数量的项,所以我尝试使用`dict.popitem`,我认为它是随机的,但似乎不是。
正如文档所说:
“从字典中删除并返回任意(键、值)对。”
对于我的问题,假设我有一个像这样的字典(例如):
>>> d = dict(zip((string.ascii_lowercase), range(1, 10)))
>>> d
{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'g': 7, 'f': 6, 'i': 9, 'h': 8}

现在我需要从中删除一些项目(数量由用户指定)。因此,我编写了以下代码:
>>> for _ in range(4):          # assume 4 items have to removed
...     d.popitem()
... 
('a', 1)
('c', 3)
('b', 2)
('e', 5)

但是这段代码存在问题,每次运行脚本时,popitem() 都会弹出完全相同的项目。你可以自由测试,我已经尝试过多次。

那么我的问题是:

  • popitem() 为什么不能按照应该的方式工作?随机删除不是随机的吗?
  • 如何从字典中随机删除项目?

12
任意并不等同于随机。 - PrettyPrincessKitty FS
2
那么这个“任意”的基础是什么? - user225312
5
可能是关于键值对内部排序的问题(这也反映在迭代顺序上——再次强调,它是任意的但不是随机的)。字典是“无序的”,但项目存储的内部顺序是确定性的——如果您考虑参数,通常即使您并不想考虑:键的哈希、插入顺序、碰撞、总项目数等。因此,以相同的方式再次创建相同的字典确实会创建相同的内部顺序。 - user395760
1
它必须是任意的,因为字典本身就是任意组织的。 - gary
6个回答

24

这就是你所说的吗?

import random
for i in range(4):
    some_dict.pop( random.choice(some_dict.keys()) )   

2
基本上,虽然我感到非常愚蠢没有想到这一点 :-) - user225312
25
这个叫做“感知狭窄”。即使popitem并不能解决你的问题,你也将注意力集中在了它身上。当事情变得困难时,你很可能是在走弯路。停下来,看看周围,喝杯茶,想想更简单的方法。 - S.Lott
2
很好的观点,不过我查了一下“感知收窄”,似乎与婴儿期大脑发育有关。再搜索一下,找到了“注意力盲区”和“认知隧道效应”。 - Patrick McElhaney
@S.Lott:文章的链接已经失效了。你能在其他地方找到另一个来源吗?谢谢! - André Caron
2
Python3:some_dict.pop(random.choice(list(some_dict.keys()))) - Johan
显示剩余2条评论

9

删除“任意”元素意味着该函数可以删除它想要的任何项目。这并不意味着它必须特别随机。

对于真正的随机性,您应该使用random模块。例如:

import random
for key in random.sample(d.keys(), 4):
   del d[key]

我现在似乎明白了,我之前对这个的理解出了些问题。 - user225312

8

popitem()是随意的但不是随机的。如果你想要访问一个随机元素

import random
key = random.choice(d.keys())
val = d[key]
del d[key]

糟糕!你比我快了。好吧,点个赞。 - Rafe Kettler

4
  • 为什么popitem()没有按照应有的方式工作?删除任意项目不是随机的吗?

任意并不等同于随机。任意只是指可能返回其中任何一个项,不能假设它们返回的顺序。

  • 如何从字典中删除随机项目?

我不敢说这是最好或最有效的方法,但其中一种方法是:

import random
dict.pop(random.choice(dict.keys())

3
为了移除指定数量的项目,我建议使用random.sample而不是重复调用dict.keysrandom.choice
for key in random.sample(d.keys(), n):
    del d[key] # or d.pop(key)

3
d = {'spam': 0,'url': 'http://www.python.org',  'title': 'Python Web Site'}
d.popitem()
print d

请尝试这个方法,我一直在尝试从字典中获取任意项,但总是会删除url,当我将其更改为

时问题得到了解决。
d = {'spam': 0,'arl': 'http://www.python.org',  'title': 'Python Web Site'}
d.popitem()
print d

注意:将URL中的'u'更改为'a'

删除标题

我猜它会从列表中删除ASCII值最高的项目,仅仅是猜测。


popitem 就是我要找的! - PascalVKooten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接