【问题标题】:Search and remove from list of tuples从元组列表中搜索和删除
【发布时间】:2016-05-17 23:39:17
【问题描述】:

我有一个元组形式的待办事项列表...

[(datetime.datetime(2014, 2, 28, 0, 0), 'tutorial signons'), (datetime.datetime(2014, 4, 9, 0, 0), 'assignment 1'), (datetime .datetime(2014, 4, 22, 0, 0), 'assignment 2'), (datetime.datetime(2014, 6, 14, 0, 0), '考试学习'), (datetime.datetime(2014, 3 , 15, 0, 0), '买杂货'), (datetime.datetime(2014, 3, 20, 0, 0), '洗衣'), (datetime.datetime(2014, 3, 26, 0, 0) , '数学作业'), (datetime.datetime(2014, 3, 31, 0, 0), '写待办事项'), (datetime.datetime(2014, 4, 4, 0, 0), '申请一个job'), (datetime.datetime(2014, 4, 14, 0, 0), '拖延'), (datetime.datetime(2014, 4, 19, 0, 0), '买彩蛋'), (datetime .datetime(2014, 4, 25, 0, 0), '买澳新饼干')]

我正在尝试编写一个函数,如果待办任务与名称匹配,它将从列表中删除一个元组,如果没有找到名称,它将返回 False。这是我到目前为止所拥有的,但我总是会出错,即使任务存在。

def remove_item(todolist, name):
for t in todolist:
    if t[1] is name:
        del t
    else:
        return False

【问题讨论】:

    标签: python list tuples


    【解决方案1】:

    您的代码的问题在于您正在测试引用相等'is' 运算符)而不是值相等'==' 运算符)。

    例如

    >>> a = 'tutorial signons'
    >>> b = 'tutorial signons'
    

    a is b 将返回 False,但 a == b 将返回 True

    更多详情请见this

    因此,这应该符合您的预期:

      def remove_item(todo_list, name):
         for t in todolist:
             if t[1] == name:
                del t
             else:
                return False
    

    但是,从您正在迭代的列表中删除元素并不是一个好主意。您可能想要创建一个新列表或使用类似的东西:

    filtered_list = filter(lambda x: x[1] != 'some_string', todo_list)

    这将从列表中删除与some_sting匹配的每个元组。

    【讨论】:

      【解决方案2】:

      在迭代时从列表中删除一个项目是一个坏主意(它会弄乱列表迭代器,因此您在删除每个项目之后跳过测试项目)。如果您有两个项目要一个接一个地删除,那么您就失败了。

      有三种方法可以解决这个问题;

      1. 以相反的顺序遍历列表(有点乱,但可以)

      2. 使用列表推导 - 构建一个新列表,省略要“删除”的值。这通常是最干净的阅读。

      3. 遍历列表并保留要删除的索引列表,然后遍历要删除和删除的索引列表(项目 i - 已删除的项目数),即补偿列表收缩。也很乱。

      选项 2 看起来像

      def remove_item(todolist, name):
          result = [item for item in todolist if name != item[1]]
          if len(todolist) == len(result):
              return False  # nothing removed
          else:
              return result
      

      【讨论】:

      • 还可以选择遍历列表,跟踪未删除项目应该去的索引,并将未删除项目复制到它们最终应该进入的位置,然后在以下位置截断列表结束。这实现了线性运行时和恒定空间开销,但它的可读性往往不如列表推导式。
      【解决方案3】:

      您的代码有一些问题:

      1. 使用is 运算符比较对象身份。使用== 获得您所期望的。
      2. 在迭代过程中删除项目会破坏迭代器。相反,捕获要删除的项目的索引,并在循环外将其删除。更好的选择是 filter 列表或使用列表推导来获取新列表。
      3. 您的return False 语句的缩进错误。它应该在for 循环之外。

      我会这样写代码:

      def remove_item(todo_list, item):
          return filter(lambda x: x[1] != item, todo_list)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-11
        • 1970-01-01
        • 2010-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多