【问题标题】:Replacing for loop with one liner for deleting dictionary [duplicate]用一个衬里替换for循环以删除字典[重复]
【发布时间】:2021-11-22 16:10:41
【问题描述】:

我想问是否有任何解决方案省略这个 for 循环one lineranything

Data = [{"name": "Gill","age": "20", "id":"10001", "gender": "female"}, {"name": "Rakshit", "age": "22", "id":"10002"}]

new_Data = {"id":"10001"}

for i, x in enumerate(Data):
     if x['id'] == new_Data['id']:
          del Data[i]

【问题讨论】:

  • 使用列表理解实际上不可能从现有列表中删除一个元素(或者这不是它们的用途)
  • 你当前的实现有问题。迭代列表时不要修改列表(更改其大小)。
  • Data[:] = [d for d in Data if d['id']==new_Data['id']]

标签: python


【解决方案1】:

您可以使用列表推导来完成过滤的任务:

Data = [{"name": "Gill","age": "20", "id":"10001", "gender": "female"}, {"name": "Rakshit", "age": "22", "id":"10002"}]

new_Data = {"id":"10001"}

filtered_data = [data for data in Data if not data['id'] == new_data['id']]

【讨论】:

  • 操作没有过滤,他们正在修改现有列表
  • @Sayse 你在技术上是正确的(这是正确的最佳形式),但这是更好的方法。
  • 好的,但我想通过删除与idnew_Data['id'] 相同的字典来更新Data
  • 然后说data = [...]而不是filtered_data
  • @Sayse 公平地说,OP 的解决方案有问题。在这种情况下,如果您觉得需要实际修改数据,您可以执行 data[:] = [<list comprehesino>] 之类的操作
【解决方案2】:

如果您尝试就地删除项目,您可以通过理解来完成,但这有点不稳定:

>>> lx = [1, 2, 2, 2, 3]
>>> [lx.pop(i) for i in sorted((idx for idx, val in enumerate(lx) if val == 2), reverse=True)]
[2, 2, 2]
>>> lx
[1, 3]

这里要注意的主要事情是,您正在获取要删除的索引,然后颠倒您弹出它们的顺序。这样您就不会因为弹出较早的索引而破坏您以后的索引。

如果您担心创建不必要的列表,也可以使用生成器:

>>> lx = [1, 2, 2, 2, 3]
>>> all(lx.pop(i) for i in sorted((idx for idx, val in enumerate(lx) if val == 2), reverse=True))
True
>>> lx
[1, 3]

不过,值得注意的是,没有理由这样做。就地删除列表的主要原因是节省内存。但是在您的情况下,您将字典作为列表项。您的原始列表实际上只是保存指向这些值的指针,如果您使用简单的列表推导来过滤原始列表,它也会引用您的字典项:

>>> ls = [{"a": 1}, {"b": 2}]
>>> lx = [i for i in ls if i.get("a", False)]
>>> lx
[{'a': 1}]
>>> ls[0]["a"] = 2
>>> ls
[{'a': 2}, {'b': 2}]
>>> lx
[{'a': 2}]

这表明原始列表中的更改会反映在您的过滤列表中,即使在过滤发生之后也是如此。因此,您在创建新的过滤列表时使用的内存实际上只是引用的大小 - 相对较小。实际上,它并不慢,因为内存分配是 O(n),等于您对原始列表的迭代。因此,虽然您可以就地修改原始列表,但没有太多理由这样做,并且您可以避免一些陷阱(例如原始帖子中的那个,您可以在其中结束向上跳过项目,因为您要从前到后删除索引)。

【讨论】:

  • 甚至不要建议这个
  • @juanpa.arrivillaga 有理由不这样做吗?
  • 是的。这是对副作用使用列表理解。它不好的原因有很多,主要是风格,但它也不必要地创建了一个列表。如果您必须使用列表解析来改变已经存在的列表,您应该使用类似data[:] = [x for x in data if condition] 的东西,这样至少列表解析不会被用于副作用(同样,非常非常糟糕)。请注意,您当前的实现尤其是最坏情况 O(N**2),至少 O(N*logN),但这在线性时间内很容易完成
  • ... 甚至data[:] = (x for x in data if condition)
  • 这样做有完全正当的理由。 特别是在使用pop() 的情况下,例如您想知道要删除什么并对其进行处理。如果您的反对只是“它创建了另一个列表”,那么我们可以使用生成器。虽然它不是“pythonic”,但禁止副作用有点愚蠢,没有比“有副作用”更好的理由。
猜你喜欢
  • 2014-06-28
  • 2015-10-21
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多