嘿伙计们,我在stackoverflow上找到了另一篇文章中的代码,我发现了一些关于" for循环"的内容。如果您使用" pop"更改列表或"删除"它弄乱了内部循环的索引。如果您从列表中弹出/删除项目,它将跳过整个项目。我绕过它的方法是实际制作一个列表的副本,用于" for循环"我操纵了另一个清单。我是python的新手。
我加入了他的名单。我的程序删除了任何体重超过180或任何名为乔的人。起初我在发现这个问题时刚刚使用了d_list。然后我只是" temp_list = d_list"我认为它是一个单独的副本,但我想不是。然后我使用列表的copy属性使其工作。这样我就不会操纵列表" for循环"正在使用。
我的问题是,这是正常的,我是否正确解决它?对我来说,如果数据很大,你就不想制作数据副本。我提出的另一个选择是使用while循环而不是外部for循环。
d_list = [ {'id':1, 'Name': 'Hannah', 'weight':150}, {'id':2, 'Name':'Andrew', 'weight':200}, {'id':3, 'Name':'Joe', 'weight':180},
{'id':4, 'Name':'Joe', 'weight':180}, {'id':5, 'Name':'Steve', 'weight':200}, {'id':6, 'Name':'Joe', 'weight':180},
{'id':7, 'Name':'George', 'weight':180}]
temp_list = d_list
#temp_list = d_list.copy()
print(d_list)
i = 0
for item in temp_list: # may make a while loop
print(item, "i = ", i, end="[")
for k, v in item.items():
print(end="*")
if (k == "weight") and (v > 180):
d_list.pop(i)
print('^popped^', i, end="") # <-- pop but you need an index
i -= 1
elif (k == "Name") and (v == "Joe"):
d_list.remove(item) # <-- remove just uses item to find and remove
print("^removed^", i, end="")
i -= 1
i += 1
print("]")
print(d_list)
print("i = ", i)
答案 0 :(得分:1)
由于您发现的问题,最好通过制作合格元素的新列表来完成此类操作。此外,扫描所有键和值是愚蠢的;通过查找键来使用字典:
newlist = []
for item in d_list:
if item["weight"] <= 180 and item["Name"] != "Joe":
newlist.append(item)
如果您担心&#34;浪费&#34;那么您可以释放旧列表。空间:
del d_list
答案 1 :(得分:0)
temp_list = d_list
会创建一个引用,因此任何一个列表中的任何更改都会反映在两者中,这样肯定不起作用。 temp_list = d_list.copy()
创建一个浅层副本,它可以像temp_list = d_list[:]
那样工作,但是更好的方法是避免任何复制,只需要使用reversed
并从列表中删除元素:
for item in reversed(d_list):
if item.get("weight", 0) > 180 or item.get("Name") == "Joe":
d_list.remove(item)
i -= 1
如果你想要弹出,你可以在最后使用反向范围开始:
for i in range(len(d_list) -1 , -1, - 1):
item = d_list[i]
if item.get("weight", 0) > 180 or item.get("Name") == "Joe":
i -= 1
第三个选项是list comprehension使用d_list[:]
来改变原始对象/列表:
d_list[:] = [d for d in d_list if d.get("weight", 0) <= 180 and d.get("Name") != "Joe"]
或者将其与generator expression:
结合使用d_list[:] = (d for d in d_list if d.get("weight", 0) <= 180 and d.get("Name") != "Joe")
所有方法都会为您提供相同的输出。使用dict.get
而不是迭代所有项也是一种更有效的解决方案,我们每次迭代执行两次查找,而不是查看每个dict中的所有键和值。
使用python3的一些时间:
In [14]: %%timeit
d_list = [{'id': 1, 'Name': 'Hannah', 'weight': 150}, {'id': 2, 'Name': 'Andrew', 'weight': 200},
{'id': 3, 'Name': 'Joe', 'weight': 180},
{'id': 4, 'Name': 'Joe', 'weight': 180}, {'id': 5, 'Name': 'Steve', 'weight': 200},
{'id': 6, 'Name': 'Joe', 'weight': 180},
{'id': 7, 'Name': 'George', 'weight': 180}]
for item in reversed(d_list):
if item.get("weight", 0) > 180 or item.get("Name") == "Joe":
d_list.remove(item)
....:
100000 loops, best of 3: 4.35 µs per loop
In [15]: %%timeit
d_list = [{'id': 1, 'Name': 'Hannah', 'weight': 150}, {'id': 2, 'Name': 'Andrew', 'weight': 200},
{'id': 3, 'Name': 'Joe', 'weight': 180},
{'id': 4, 'Name': 'Joe', 'weight': 180}, {'id': 5, 'Name': 'Steve', 'weight': 200},
{'id': 6, 'Name': 'Joe', 'weight': 180},
{'id': 7, 'Name': 'George', 'weight': 180}]
for i in range(len(d_list) - 1, -1, - 1): # may make a while loop
item = d_list[i]
if item.get("weight", 0) > 180 or item.get("Name") == "Joe":
d_list.pop(i)
....:
....:
100000 loops, best of 3: 4.48 µs per loop
In [16]: %%timeit
....: d_list = [{'id': 1, 'Name': 'Hannah', 'weight': 150}, {'id': 2, 'Name': 'Andrew', 'weight': 200},
....: {'id': 3, 'Name': 'Joe', 'weight': 180},
....: {'id': 4, 'Name': 'Joe', 'weight': 180}, {'id': 5, 'Name': 'Steve', 'weight': 200},
....: {'id': 6, 'Name': 'Joe', 'weight': 180},
....: {'id': 7, 'Name': 'George', 'weight': 180}]
....: d_list[:] = (d for d in d_list if d.get("weight", 0) <= 180 and d.get("Name") != "Joe")
....:
100000 loops, best of 3: 3.23 µs per loop
In [17]: %%timeit
d_list = [{'id': 1, 'Name': 'Hannah', 'weight': 150}, {'id': 2, 'Name': 'Andrew', 'weight': 200},
{'id': 3, 'Name': 'Joe', 'weight': 180},
{'id': 4, 'Name': 'Joe', 'weight': 180}, {'id': 5, 'Name': 'Steve', 'weight': 200},
{'id': 6, 'Name': 'Joe', 'weight': 180},
{'id': 7, 'Name': 'George', 'weight': 180}]
d_list[:] = [d for d in d_list if d.get("weight", 0) <= 180 and d.get("Name") != "Joe"]
....:
100000 loops, best of 3: 2.98 µs per loop
因此列表comp是最快的,然后是gen exp。如果您知道密钥始终存在,那么使用d["weight"]
等进行访问也会更快