【问题标题】:Removing items randomly from a dictionary从字典中随机删除项目
【发布时间】:2011-06-16 02:15:32
【问题描述】:

如何在 Python 中从字典中删除随机项?

我必须从字典中删除指定数量的项目,所以我尝试使用dict.popitem,我认为这是随机的,但似乎不是。

正如docs 所说:

移除并返回一个任意的 (key, value) 字典中的对。

对于我的问题,假设我有一个像(示例)这样的字典:

>>> 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() 没有按应有的方式工作?删除任意项目不是随机的吗?
  • 如何从字典中删除随机项?

【问题讨论】:

  • 任意!=随机。
  • 那么这个arbitrary是基于什么?
  • 可能在对的内部排序上(这也反映在迭代顺序上——这也是随意的,但不是随机的)。字典是“无序的”,但项目在内部存储的顺序是确定性的 - 如果您考虑到通常甚至不会想到的参数:键的哈希值、插入顺序、冲突, 总项目数...因此再次以相同方式创建相同的字典确实会创建相同的内部排序。
  • 它必须是任意的,因为字典本身是任意组织的。

标签: python random dictionary


【解决方案1】:

你说的是这个吗?

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

【讨论】:

  • 差不多,虽然我觉得自己真的很愚蠢,没想到这一点:-)
  • 这叫做“知觉缩小”。您缩小了注意力以了解有关 popitem 的所有内容,即使它没有解决您的问题。当事情看起来很困难时,你可能做错了。停止。看看周围。喝茶。想想更简单的事情。
  • 好点,但是,我查了“知觉变窄”,它似乎与婴儿期大脑的发育方式有关。更多的谷歌搜索出现了"inattention blindness""cognitive tunneling"
  • @S.Lott:文章的链接已失效。你能在某个地方找到另一个来源吗?谢谢!
  • @PatrickMcElhaney 如果您在互联网上的其他地方查找知觉缩小,它确实描述了 S.Lott 的建议。也许这是这个词的更通俗的用法?我认为他只是意味着您可以专注于某件事(“这必须是解决方案!”)并浪费大量时间深入研究它,如果您只是休息一下并退后一步,您可能已经看到别的东西是一个更有希望的解决方案。我倾向于自己用代码来做这件事,这就是为什么(我认为)我理解他在说什么。 (“认知隧道”也可能是他所暗示的)。
【解决方案2】:

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

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

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

【讨论】:

  • 我现在似乎明白了这一点。
【解决方案3】:

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

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

【讨论】:

  • 该死!打败我。哦,好吧,+1。
【解决方案4】:
  • 为什么 popitem() 没有按应有的方式工作?删除任意项目不是随机的吗?

任意并不意味着随机。任意只是意味着任何物品都可以退回,并且不应该假设它们退回的顺序。

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

我并不认为这是最好或最有效的方法,但一种方法是:

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

【讨论】:

    【解决方案5】:

    为了删除指定数量的项目,我会使用random.sample 而不是重复调用dict.keysrandom.choice

    for key in random.sample(d.keys(), n):
        del d[key] # or d.pop(key)
    

    【讨论】:

      【解决方案6】:
      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 正是我想要的!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 2012-08-31
      • 2016-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多