【问题标题】:Python: How to change list item, if item also exists in another listPython:如何更改列表项,如果项目也存在于另一个列表中
【发布时间】:2021-09-10 14:05:25
【问题描述】:

有一个列表包含“托尔金”书籍,另一个包含“指环王”书籍。

《指环王》中的一些书与《托尔金》中的书相同。

我想使用 for 循环来检查“托尔金”书籍中的哪些书籍与“指环王”书籍中的书籍相同。如果 for 循环找到匹配项,它会将 Tolkien 列表中的项目更改为“LOTR book: {Tolkien book}”

我的问题是: for 循环改变了托尔金列表中的项目。 我知道它会重新匹配匹配项,但它不会更改列表。 这是为什么呢?

Lord_Of_The_Rings = ["The Hobbit", "The Fellowship of the Ring", "The Two Towers", \
"The Return of the King"]

Tolkien_books = ["The Hobbit", "Farmer Giles of Ham", "The Fellowship of the Ring", \
"The Two Towers", "The Return of the King", "The Adventures of Tom Bombadil", "Tree and Leaf"]



for T_book in Tolkien_books:
    for LOTR_book in Lord_Of_The_Rings:

        if LOTR_book == T_book:
            T_book = f"LOTR: {T_book}"

print(Tolkien_books)

【问题讨论】:

  • T_book = 不会更改 T_book 所引用的对象,它会更改 T_book 以引用不同的对象。

标签: python list loops for-loop


【解决方案1】:

这是 python 名称绑定工作原理的基础。我要画一些图,因为这样更容易理解。

将对象绑定到名称会创建引用。您从两个名称开始,Lord_Of_The_Rings 和 Tolkein_Books,它们指的是列表。列表元素引用了一些字符串。请注意,字符串未绑定到名称,但可以使用列表上的索引来访问:

在循环for T_book in Tolkien_books: 中,第二个列表的每个连续元素都被分配给名称T_book。第一次迭代如下所示:

如果匹配Lord_Of_The_Rings 中的元素,'The Hobbit' 匹配,则匹配T_book = f"LOTR: {T_book}"。这意味着您将一个新的字符串对象绑定到名称T_book,如下所示:

然而,您的目标是更新列表Tolkein_books 的第一个元素,我们将其命名为Tolkein_books[0]。所以需要将赋值T_book = f"LOTR: {T_book}"切换为Tolkein_books[0] = f"LOTR: {T_book}":

请注意,名称 T_book 仍将引用曾经在 Tolkein_books[0] 中的原始 "The Hobbit" 字符串对象。多个名称可以引用同一个对象。

实际上,要按索引引用列表项,您需要遍历索引。您可以使用内置的 enumerate 来迭代字符串和索引。

您也不需要嵌套循环。 in 运算符为您将其隐藏在 list.__contains__ 中。您可以遍历要更改的列表的索引并随时更新:

for i, name in enumerate(Tolkien_Books):
    if name in Lord_Of_The_Rings:
        Tolkein_Books[i] = f'LOTR: {name}'

您也可以丢弃原始的Tolkein_books 列表,并将其替换为包含所需字符串的更新版本:

Tolkein_Books = [f'LOTR: {name}' if name in Lord_Of_The_Rings else name for name in Tolkien_Books]

【讨论】:

    【解决方案2】:

    你正在改变变量T_book的值,而不是列表的元素,你可以试试这个:

    Lord_Of_The_Rings = ["The Hobbit", "The Fellowship of the Ring", "The Two Towers", "The Return of the King"]
    
    Tolkien_books = ["The Hobbit", "Farmer Giles of Ham", "The Fellowship of the Ring", "The Two Towers", "The Return of the King", "The Adventures of Tom Bombadil", "Tree and Leaf"]
    
    
    
    for i, T_book in enumerate(Tolkien_books):
        for LOTR_book in Lord_Of_The_Rings:
    
            if LOTR_book == T_book:
                Tolkien_books[i] = f"LOTR: {T_book}"
    
    print(Tolkien_books)
    

    【讨论】:

      【解决方案3】:

      您正在更改 for 循环变量 T_book,它引用的对象与 Tolkien_books 列表中的对象不同。

      您可以这样做:

      Lord_Of_The_Rings = ["The Hobbit", "The Fellowship of the Ring", "The Two Towers",
      "The Return of the King"]
      
      Tolkien_books = ["The Hobbit", "Farmer Giles of Ham", "The Fellowship of the Ring",
      "The Two Towers", "The Return of the King", "The Adventures of Tom Bombadil", "Tree and Leaf"]
      
      Tolkien_books = [f'LOTR: {book}' if book in Lord_Of_The_Rings else book for book in Tolkien_books]
      

      返回:

      ['LOTR: The Hobbit', 'Farmer Giles of Ham', 'LOTR: The Fellowship of the Ring', 'LOTR: The Two Towers', 'LOTR: The Return of the King', 'The Adventures of Tom Bombadil', 'Tree and Leaf']
      

      【讨论】:

        【解决方案4】:

        这是因为您只更改了变量 T_Book,而不是列表中的实际元素。

        for index1, T_Book in enumerate(Tolkien_books):
            for index2, LOTR_book in enumerate(Lord_Of_The_Rings):
                if LOTR_book == T_book:
                    Tolkien_books[index1] = f"LOTR: {T_book}"
        

        【讨论】:

        • 你在两个循环中都使用了index,它将无法工作
        • 谢谢!修好了。
        【解决方案5】:

        使用列表推导过滤两个列表,然后重新组合。 (我知道我没有回答这个问题,所以这只是一种替代方法)

        list = [x for x in Tolkien_books if x in Lord_Of_The_Rings]
        print(list)
        combined_list = ["LOTR: [{}]".format(x) for x in Tolkien_books if x in Lord_Of_The_Rings] + [x for x in Tolkien_books if x not in Lord_Of_The_Rings]
        print(combined_list)
        

        【讨论】:

        • 问题是“为什么会这样?”
        • 他们还想更改Tolkien_books 中的字符串。将 someting 分配给名为 list 的变量也不是最好的主意
        • 在2021年使用Python 3语法可能是个好主意,即写print(x)而不是print x :)
        • OP 不想过滤项目
        • 我只是在查看您的回答,克里斯。看起来很干净 :) 我会记住这一点的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-04
        • 2013-12-12
        • 2017-06-06
        • 2022-11-12
        • 1970-01-01
        • 1970-01-01
        • 2016-01-26
        相关资源
        最近更新 更多