【问题标题】:Python List remove multiple itemsPython List 删除多个项目
【发布时间】:2018-11-18 02:29:57
【问题描述】:

我正在尝试从列表中删除多次出现的值。输出不会删除任何所需的项目。

def rem(a,li):
try:
    while a in li == True:
        li.remove(a)
    print('Updated list: ',li)
except ValueError:
    print(a,' is not located in the list ',li)

功能试用示例:

L = [1,2,3,45,3,2,3,3,4,5]

rem(2,L)

输出:更新列表:[1, 2, 3, 45, 3, 2, 3, 3, 4, 5]

【问题讨论】:

  • 它是否打算完全删除该值?还是您只想减少一个实例。
  • 您的预期输出是什么?您是要删除所有出现的a 还是仅删除重复的?例如如果lst = [1,2,3,4,5,5] 并且你调用rem(5,lst),你期待输出[1,2,3,4,5] 还是[1,2,3,4]

标签: python python-3.x list


【解决方案1】:

您的代码中有 2 个错误。第一个是

while a in li == True: 实际上,这个检查总是返回 False,因为 li == TrueFalse

实际上应该是while (a in li) == True:,或者while a in li:

此外,如果您尝试仅删除 重复 次出现的 a(即保留第一次出现的 a),那么列表解析将不适合您的需要。您必须在 rem() 函数中添加一个额外的检查,以捕获第一次出现的 a 并且 然后 执行您的循环:

def rem(a, li):
  list_length = len(li)
  i = 0
  while (li[i] != a) and (i < list_length):
    i += 1              # skip to the first occurrence of a in li
  i += 1                # increment i 
  while i < list_length:
    if li[i] == a:
      del li[i]
      print('Updated list: ', li)
      list_length -= 1          # decrement list length after removing occurrence of a
    else:
      i += 1

上面的代码sn-p没有覆盖列表为空的边缘情况,或者a不在列表中的情况。我会把这些练习留给你。

【讨论】:

  • 对于这么简单的任务来说这是相当复杂的。
【解决方案2】:

尝试将while条件更改为while a in li

def rem(a,li):
    try:
        while a in li:
            li.remove(a)
        print('Updated list: ',li)
    except ValueError:
        print(a,' is not located in the list ',li)

L = [1,2,3,45,3,2,3,3,4,5]
rem(2,L)

一般来说,如果您想从列表中删除重复项,则可以使用内置的set

【讨论】:

  • 谢谢你的作品。 python是否将li中的a解释为已经包含等于True的比较?这是我可以从代码中推断出的唯一逻辑。
  • @evan 是的,你是对的!从其他答案中可以看出,有更好的方法来做到这一点。
  • 尝试...除了...有什么意义?您已经拥有while a in li,因此当调用li.remove(a) 时,a 必须在li 中。 ValueError 何时会出现? (要成为可接受的答案,应删除不必要的代码)
  • @abccd 感谢您的反馈;这个概念对我来说很新,将继续前进。
【解决方案3】:

假设您想从L 中删除a 的所有实例,您也可以只使用简单的列表推导:

def rem(a,li):
    return [x for x in li if x != a]

L = [1,2,3,45,3,2,3,3,4,5]
print(rem(2,L))

哪些输出:

[1, 3, 45, 3, 3, 3, 4, 5]

【讨论】:

    【解决方案4】:

    对于列表理解来说,这将是一项更好的工作。 L[:] = [a for a in L if a not in (2,)] 分配给切片将使列表发生变化。



    我正在更新我的答案,以说明您的问题允许的各种解释 并且通过同时接受 字符串多个值 来使其更通用。

    def removed(items, original_list, only_duplicates=False, inplace=False):
        """By default removes given items from original_list and returns
        a new list. Optionally only removes duplicates of `items` or modifies
        given list in place.
        """
        if not hasattr(items, '__iter__') or isinstance(items, str):
            items = [items]
    
        if only_duplicates:
            result = []
            for item in original_list:
                if item not in items or item not in result:
                    result.append(item)
        else:
            result = [item for item in original_list if item not in items]
    
        if inplace:
            original_list[:] = result
        else:
            return result
    

    文档字符串扩展:

    """
    Examples:
    ---------
    
        >>>li1 = [1, 2, 3, 4, 4, 5, 5]
        >>>removed(4, li1)
           [1, 2, 3, 5, 5]
        >>>removed((4,5), li1)
           [1, 2, 3]
        >>>removed((4,5), li1, only_duplicates=True)
           [1, 2, 3, 4, 5]
    
        # remove all duplicates by passing original_list also to `items`.:
        >>>removed(li1, li1, only_duplicates=True)
          [1, 2, 3, 4, 5]
    
        # inplace:
        >>>removed((4,5), li1, only_duplicates=True, inplace=True)
        >>>li1
            [1, 2, 3, 4, 5]
    
        >>>li2 =['abc', 'def', 'def', 'ghi', 'ghi']
        >>>removed(('def', 'ghi'), li2, only_duplicates=True, inplace=True)
        >>>li2
            ['abc', 'def', 'ghi']
    """
    

    您应该清楚自己真正想要做什么,修改现有列表,或创建一个新列表 缺少的具体项目。如果您有第二个参考点,那么区分这一点很重要 到现有列表。例如,如果您有...

    li1 = [1, 2, 3, 4, 4, 5, 5]
    li2 = li1
    # then rebind li1 to the new list without the value 4
    li1 = removed(4, li1)
    # you end up with two separate lists where li2 is still pointing to the 
    # original
    li2
    # [1, 2, 3, 4, 4, 5, 5]
    li1
    # [1, 2, 3, 5, 5]
    

    这可能是也可能不是您想要的行为。

    【讨论】:

    • 如果您不在乎是否创建了新列表,则没有必要,但是问题的表达方式我知道他想要改变列表,而不是替换它。您可以通过id(L) 检查分配给切片时列表是否仍与以前相同,但如果您跳过切片,它会获得一个新的 id。
    【解决方案5】:

    只需跟踪索引号并使用del

    简单的方法:

    L = [1,2,3,45,3,2,3,3,4,5]
    
    def rem(a,li):
        for j,i in enumerate(li):
            if a==i:
                del li[j]
    
        return li
    
    
    
    print(rem(2,L))
    

    输出:

    [1, 3, 45, 3, 3, 3, 4, 5]
    

    【讨论】:

      猜你喜欢
      • 2015-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      相关资源
      最近更新 更多