【问题标题】:Is it safe to remove dictionary keys while iterating over it? [duplicate]迭代时删除字典键是否安全? [复制]
【发布时间】:2019-09-26 15:08:49
【问题描述】:

我编写了一些执行此操作的代码,并且运行良好,但在查看代码时,我意识到我所做的可能不适用于其他语言。

举一个人为的例子:

dict := map[string]string{ "a": "1", "b": "2" }

for key, val := range dict {
  fmt.Println(val)
   delete(dict, "b")
}

这会打印“1”和“2”,然后当我检查dict 时,它只是{ "a": "1" }

所以,我觉得这样做安全的,但我想知道为什么?

range dict 是否在内部创建副本?

【问题讨论】:

  • @colminator 不是重复的。 OP 询问如果在之前的迭代中删除了另一个元素,是否会打印它。
  • OP没有问这个。
  • 嗯,实际问题的措辞几乎与Is it safe to remove selected keys from map within a range loop 相同,而答案只是引用自规范。
  • 它们是同一枚硬币的两个方面......这个问题的重点是它安全的情况,但我的问题更具体地是关于它的情况不安全(我的代码在问题中)
  • 但是它安全的,那么问题有什么不同呢?此外,迭代顺序是不确定的,因此您的示例可能会在运行时打印一个或两个值。

标签: go


【解决方案1】:

一如既往,the spec 是明确的答案。向下滚动到“For statements with range clause”,第 3 项(强调我的):

未指定映射的迭代顺序,也不保证从一次迭代到下一次迭代顺序相同。 如果在迭代过程中移除了一个尚未到达的map entry,则不会产生对应的迭代值。如果在迭代期间创建了映射条目,则该条目可能在迭代期间产生或可能被跳过。对于创建的每个条目以及从一个迭代到下一个迭代,选择可能会有所不同。如果map为nil,则迭代次数为0。

【讨论】:

  • 谢谢你。因此,我在问题中的示例将无法可靠地工作。如果我只删除当前正在处理的密钥(类似于 Ruby 的delete_if)会怎样?这将是安全的,因为被删除的地图条目已经在迭代期间已经到达?
  • @maxpleaner 如果我做对了,如果你在同一次迭代中删除了密钥,它仍然可以工作,因为它已经加载到循环的keyval 中。
猜你喜欢
  • 2014-10-03
  • 2010-10-07
  • 2011-03-28
  • 2011-09-04
  • 1970-01-01
  • 2017-03-13
  • 2015-04-03
  • 1970-01-01
  • 2012-02-18
相关资源
最近更新 更多