【问题标题】:python and iteration specifically "for line in first_names"python和迭代专门“for line in first_names”
【发布时间】:2022-01-12 13:47:48
【问题描述】:

如果我在 python 中从数组中“弹出”一个项目,我似乎会因为弄乱数组的总长度而在脚上开枪?请参见以下示例: 我只是一个白痴还是这是正常行为?有没有更好的方法来实现我想要做的事情?

first_names = []
last_names = []
approved_names = []
blacklisted_names = []
loopcounter = 0

with open("first_names.txt") as file:
    first_names = file.readlines()
    #first_names = [line.rstrip() for line in first_names]

for line in first_names:
    line = line.strip("\r\n")
    line = line.strip("\n")
    line = line.strip(" ")
    if line == "":
        first_names.pop(loopcounter)
        #first_names.pop(first_names.index("")) # Does not work as expected
        #loopcounter -= 1 # Does not work as expected either......
    loopcounter += 1
        
loopcounter = 0


def save_names():
    with open("first_names2.txt",'wt',encoding="utf-8") as file:
        file.writelines(first_names)

以及生成的文件:

first_names.txt 
{

Abbey
Abbie
Abbott
Abby


Abe
Abie
Abstinence
Acton
}

还有输出文件

{
Abbey
Abbie
Abbott


Abe
Abie
Abstinence
Acton
}

【问题讨论】:

  • 代码的语法高亮 代码块可以使用 highlight.js 高亮。在许多情况下,语法高亮语言将从问题的标签中推断出来。要手动指定围栏代码块的语言,请将语言添加到带有打开围栏的行:``` lang-js setTimeout(function () { alert("JavaScript"); }, 1000); ```stackoverflow.com/editing-help#syntax-highlighting
  • 我也尝试在“for line, index in first_names:”中请求索引,但它引发了异常......
  • 文本文件中是否有一堆不同的空白字符,您不能仅使用 strip() 处理?
  • @KennyOstrom 除了我放入其中的垃圾之外,它会接受用户输入,我想确保我清理了文件,我不会费心做任何关于你持有的事情down alt ant 在数字小键盘上击中随机数字......所以让我想知道我为什么要这样做............

标签: python for-loop iteration


【解决方案1】:

正如您在问题中所说,一般来说,对您正在迭代的列表进行变异不是一个好主意。如果从列表中弹出一个元素,不一定会弄乱数组的长度,但在处理要弹出的索引时可能会遇到意外行为。在这种情况下,您可以跳过数组的某些元素。

一种快速的解决方案是复制列表并使用内置的enumerate() 方法,如下所示:

copy = first_names.copy()
for i, line in enumerate(copy):
    line = line.strip("\r\n")
    line = line.strip("\n")
    line = line.strip(" ")
    if line == "":
        first_names.remove(i)

更多关于enumerate()here

【讨论】:

  • 感谢您的提醒,想知道为什么它会这样,并且不知道枚举功能......
  • 如果我(从原始数组中)删除一个元素,然后再从原始数组中删除另一个元素,这是否也会不同步?
  • 您应该在每次想要添加和/或删除元素时复制您将要操作的列表。
  • 好的,谢谢,所以我每次删除或添加东西时都必须重新运行迭代,知道有用!我希望我可以投票或将多个回复标记为答案....感谢您的宝贵时间!
【解决方案2】:

list.pop() 从列表中删除一个项目并返回值(参见例如this ref)。对于清理和编写名称列表的非常基本的任务,一个简单的编辑是:

with open("first_names.txt") as file:
    first_names = file.readlines()

cleaned_lines = []
for line in first_names:
    clean_l = line.strip("\r\n").strip("\n").strip(" ")
    if clean_l != "":
        cleaned_lines.append(clean_l)

with open("first_names2.txt",'wt',encoding="utf-8") as file:
    file.writelines(cleaned_lines)

如果您不想创建列表 first_names 的干净副本,您也可以迭代地将单行附加到文件中。

with open("first_names.txt") as file:
    first_names = file.readlines()

with open("first_names2.txt",'wt',encoding="utf-8") as file:
    for line in first_names:
        clean_l = line.strip("\r\n").strip("\n").strip(" ")
        if clean_l != "":
            file.writelines([clean_l, ])

【讨论】:

  • 我将此标记为答案,因为它最接近我的原始程序流程。我希望我可以投票或将多个回复标记为答案....感谢您的宝贵时间!
  • 我将继续使用这个我希望我可以在 stackoverflow.com 上正确发布代码作为评论:def cleanselist(input_list):cleaned_lines = [] for line in input_list: clean_l = line .strip("\r\n").strip("\n").strip(" ") if clean_l != "": clean_lines.append(clean_l) return clean_lines
  • 在调用 save 之前也需要这样做: def cleanselistbyaddinglineterminators(input_list): clean_lines = [] for line in input_list: line = line +"\n"cleanse_lines.append(line) return clean_lines跨度>
【解决方案3】:

通常的做法是过滤或创建一个新列表,而不是更改您正在迭代的列表。使用您想要的更改创建一个新列表,然后将其分配回原始变量名称并不少见。这是一个列表理解。注意过滤掉不需要的空行的 if 语句。

first_names = [name.strip() for name in first_names if name.strip()]

https://docs.python.org/3/glossary.html#term-list-comprehension

您可以对迭代器执行相同的操作,使用 map 将函数应用于列表中的每个项目,并过滤以删除空行。

first_names_iterator = filter(lambda x: bool(x), map(lambda x: x.strip(), first_names))
first_names = list(first_names_iterator)

https://docs.python.org/3/library/functions.html#map
https://docs.python.org/3/library/functions.html#filter

最后一行演示了您可以将迭代器传递给列表的构造函数以获取列表,但迭代器更好。您可以遍历它们,而不必一次获得整个列表。如果你想要一个列表,你应该使用列表推导。

lambda 表示法只是编写函数的一种快速方法。我本可以定义一个具有好名称的函数,但对于 map、filter 或排序键之类的东西来说,这通常是多余的。

完整代码:

test_cases = [
    'Abbey',
    '  Abbie  ',
    '',
    'Acton',
]

print(test_cases)
first_names = list(test_cases)
first_names = [name.strip() for name in first_names if name.strip()]
print(first_names)

first_names = list(test_cases)
for name in filter(lambda x: bool(x),
                   map(lambda x: x.strip(),
                       first_names)):
    print(name)

【讨论】:

  • 我可能应该在列表理解中嵌套一个生成器而不是计算 name.strip() 两次,但我想继续使用迭代器。
  • 好的,谢谢,我正在阅读您现在发布的文档,我希望我可以投票或标记多个回复作为答案....感谢您的宝贵时间!
猜你喜欢
  • 1970-01-01
  • 2019-04-18
  • 1970-01-01
  • 2019-06-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 2020-10-20
相关资源
最近更新 更多