aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ChrisJL <[email protected]>2024-11-23 19:18:28 +0000
committerGravatar GitHub <[email protected]>2024-11-23 19:18:28 +0000
commit9567dddccb86c1e0c56aa3d17f76c70f6726068b (patch)
treecb147697329589a998e8bc26091717d9ee81f26d
parentBranding: improve decorator name (diff)
parentMerge branch 'main' into feat/tag-list-iterate-and-remove-gotcha (diff)
Merge pull request #3018 from python-discord/feat/tag-list-iterate-and-remove-gotcha
feat: tag loop-remove
-rw-r--r--bot/resources/tags/loop-remove.md27
1 files changed, 27 insertions, 0 deletions
diff --git a/bot/resources/tags/loop-remove.md b/bot/resources/tags/loop-remove.md
new file mode 100644
index 000000000..f43097a2d
--- /dev/null
+++ b/bot/resources/tags/loop-remove.md
@@ -0,0 +1,27 @@
+---
+aliases: ["loop-add", "loop-modify"]
+embed:
+ title: "Removing items inside a for loop"
+---
+Avoid adding to or removing from a collection, such as a list, as you iterate that collection in a `for` loop:
+```py
+data = [1, 2, 3, 4]
+for item in data:
+ data.remove(item)
+print(data) # [2, 4] <-- every OTHER item was removed!
+```
+Inside the loop, an index tracks the current position. If the list is modified, this index may no longer refer to the same element, causing elements to be repeated or skipped.
+
+In the example above, `1` is removed, shifting `2` to index *0*. The loop then moves to index *1*, removing `3` (and skipping `2`!).
+
+You can avoid this pitfall by:
+- using a **list comprehension** to produce a new list (as a way of filtering items):
+ ```py
+ data = [x for x in data if x % 2 == 0]
+ ```
+- using a `while` loop and `.pop()` (treating the list as a stack):
+ ```py
+ while data:
+ item = data.pop()
+ ```
+- considering whether you need to remove items in the first place!