Python 从列表中删除多个元素

Python 从列表中删除多个元素,python,list,Python,List,是否可以同时从列表中删除多个元素?如果我想删除索引0和2处的元素,并尝试类似于del somelist[0],然后是del somelist[2],那么第二条语句实际上会删除somelist[3] 我想我总是可以先删除编号较高的元素,但我希望有更好的方法。如果要删除多个不相邻的项目,那么您描述的是最好的方法(是的,请确保从最高索引开始) 如果项目相邻,则可以使用切片分配语法: a[2:10] = [] 您可以使用枚举并删除其索引与要删除的索引匹配的值: indices = 0, 2 somel

是否可以同时从列表中删除多个元素?如果我想删除索引0和2处的元素,并尝试类似于
del somelist[0]
,然后是
del somelist[2]
,那么第二条语句实际上会删除
somelist[3]


我想我总是可以先删除编号较高的元素,但我希望有更好的方法。

如果要删除多个不相邻的项目,那么您描述的是最好的方法(是的,请确保从最高索引开始)

如果项目相邻,则可以使用切片分配语法:

a[2:10] = []

您可以使用
枚举
并删除其索引与要删除的索引匹配的值:

indices = 0, 2
somelist = [i for j, i in enumerate(somelist) if j not in indices]
作为一项功能:

def multi_delete(list_, *args):
    indexes = sorted(list(args), reverse=True)
    for index in indexes:
        del list_[index]
    return list_

n log(n)时间内运行,这将使它成为迄今为止最快的正确解决方案。

您可以在dict上这样做,而不是在列表上。在列表中,元素是按顺序排列的。在dict中,它们只依赖于索引

简单的代码,仅通过以下操作进行解释:

反之亦然:

lst = [dct[i] for i in sorted(dct.keys())] 

无论如何,我认为最好像你说的那样开始从较高的索引中删除。

我实际上可以想出两种方法:

  • 对列表进行切片,如下所示(这将删除第一、第三和第八个元素)

    somelist=somelist[1:2]+somelist[3:7]+somelist[8:]

  • 在适当的地方这样做,但一次一个:

    somelist.pop(2) somelist.pop(0)


  • 那么,您实际上想要在一次过程中删除多个元素?在这种情况下,要删除的下一个元素的位置将被先前删除的元素的数量所抵消

    我们的目标是删除所有元音,这些元音被预先计算为索引1、4和7。请注意,重要的是删除索引是按升序排列的,否则它将不起作用

    to_delete = [1, 4, 7]
    target = list("hello world")
    for offset, index in enumerate(to_delete):
      index -= offset
      del target[index]
    

    如果你想以任何顺序删除元素,那就更复杂了。在我看来,排序
    以删除
    可能比计算什么时候应该或不应该从
    索引中减去要容易得多。作为格雷格答案的一个专门化,你甚至可以使用扩展切片语法。例如,如果要删除项目0和2:

    >>> a= [0, 1, 2, 3, 4]
    >>> del a[0:3:2]
    >>> a
    [1, 3, 4]
    

    当然,这不包括任何任意选择,但它确实可以用于删除任意两个项目。

    这里有另一种方法,可以在适当的位置删除元素。此外,如果你的列表很长,它会更快

    >>> a = range(10)
    >>> remove = [0,4,5]
    >>> from collections import deque
    >>> deque((list.pop(a, i) for i in sorted(remove, reverse=True)), maxlen=0)
    
    >>> timeit.timeit('[i for j, i in enumerate(a) if j not in remove]', setup='import random;remove=[random.randrange(100000) for i in range(100)]; a = range(100000)', number=1)
    0.1704120635986328
    
    >>> timeit.timeit('deque((list.pop(a, i) for i in sorted(remove, reverse=True)), maxlen=0)', setup='from collections import deque;import random;remove=[random.randrange(100000) for i in range(100)]; a = range(100000)', number=1)
    0.004853963851928711
    

    我是Python的初学者,目前的编程至少可以说是粗糙和肮脏的,但我的解决方案是结合使用我在早期教程中学习的基本命令:

    some_list = [1,2,3,4,5,6,7,8,10]
    rem = [0,5,7]
    
    for i in rem:
        some_list[i] = '!' # mark for deletion
    
    for i in range(0, some_list.count('!')):
        some_list.remove('!') # remove
    print some_list
    
    显然,由于必须选择“删除标记”字符,这有其局限性


    至于列表规模的性能,我确信我的解决方案是次优的。然而,它很简单,我希望对其他初学者有吸引力,并且在一些简单的情况下也能工作,
    一些列表是众所周知的格式,例如,总是数字…

    这里有一个替代方案,它不使用enumerate()创建元组(如SilentGhost的原始答案)

    这对我来说似乎更容易理解。(如果我习惯使用enumerate,我可能会有不同的感觉。)警告:我还没有测试这两种方法的性能

    # Returns a new list. "lst" is not modified.
    def delete_by_indices(lst, indices):
        indices_as_set = set(indices)
        return [ lst[i] for i in xrange(len(lst)) if i not in indices_as_set ]
    
    注意:Python2.7语法。对于Python3,
    xrange
    =>
    range

    用法:

    lst = [ 11*x for x in xrange(10) ]
    somelist = delete_by_indices( lst, [0, 4, 5])
    
    somelist = delete__by_values( lst, [0, 44, 55] )
    
    人物列表:

    [11, 22, 33, 66, 77, 88, 99]
    
    [11, 22, 33, 66, 77, 88, 99]
    

    ---奖金---

    从列表中删除多个值。也就是说,我们有要删除的值:

    # Returns a new list. "lst" is not modified.
    def delete__by_values(lst, values):
        values_as_set = set(values)
        return [ x for x in lst if x not in values_as_set ]
    
    用法:

    lst = [ 11*x for x in xrange(10) ]
    somelist = delete_by_indices( lst, [0, 4, 5])
    
    somelist = delete__by_values( lst, [0, 44, 55] )
    
    人物列表:

    [11, 22, 33, 66, 77, 88, 99]
    
    [11, 22, 33, 66, 77, 88, 99]
    

    这与之前的答案相同,但这次我们提供了要删除的值
    [0,44,55]

    删除方法将导致列表元素大量移动。我认为最好复印一份:

    ...
    new_list = []
    for el in obj.my_list:
       if condition_is_true(el):
          new_list.append(el)
    del obj.my_list
    obj.my_list = new_list
    ...
    

    这一点已经被提到,但不知何故,没有人能够真正做到正确

    O(n)
    上,解决方案是:

    indices = {0, 2}
    somelist = [i for j, i in enumerate(somelist) if j not in indices]
    

    这非常接近,但增加了两个大括号。

    出于某种原因,我不喜欢这里的任何答案。 是的,它们可以工作,但严格地说,它们中的大多数并没有删除列表中的元素,是吗?(但制作一份副本,然后用编辑过的副本替换原始副本)

    为什么不先删除较高的索引

    这有什么原因吗? 我只想:

    for i in sorted(indices, reverse=True):
        del somelist[i]
    
    如果你真的不想向后删除项目,那么我想你应该只增加大于上次删除索引的索引值(因为你有不同的列表,所以不能真正使用相同的索引)或使用列表的副本(不是“删除”,而是用编辑过的副本替换原始索引)


    我是否遗漏了什么,有没有理由不按相反顺序删除?

    从技术上讲,答案是不可能同时删除两个对象。但是,可以在一行漂亮的python中删除两个对象

    del (foo['bar'],foo['baz'])
    

    将重复删除
    foo['bar']
    ,然后
    foo['baz']
    您可以使用
    numpy。删除如下所示:

    import numpy as np
    a = ['a', 'l', 3.14, 42, 'u']
    I = [0, 2]
    np.delete(a, I).tolist()
    # Returns: ['l', '42', 'u']
    

    如果您不介意以
    numpy
    数组结尾,可以省去
    .tolist()
    。您还应该看到一些相当大的速度改进,使其成为一个更具可扩展性的解决方案。我还没有对它进行基准测试,但是
    numpy
    操作是用C或Fortran编写的编译代码。

    另一种使用列表索引值的列表理解方法:

    stuff = ['a', 'b', 'c', 'd', 'e', 'f', 'woof']
    index = [0, 3, 6]
    new = [i for i in stuff if stuff.index(i) not in index]
    
    这将返回:

    ['b', 'c', 'e', 'f']
    

    我们可以在索引列表按降序排序后,使用for循环对索引进行迭代

    mylist=[66.25, 333, 1, 4, 6, 7, 8, 56, 8769, 65]
    indexes = 4,6
    indexes = sorted(indexes, reverse=True)
    for i in index:
        mylist.pop(i)
    print mylist
    

    对于列表A中的索引0和2:

    for x in (2,0): listA.pop(x)
    
    对于要从列表A中删除的一些随机索引:

    indices=(5,3,2,7,0) 
    for x in sorted(indices)[::-1]: listA.pop(x)
    

    从中概括评论。在实现的任何类中,尤其是在
    列表中,项目删除都是通过
    \uu delitem\uuu
    魔术方法完成的。此方法的工作原理类似于
    \uuuu getitem\uuu
    ,这意味着它可以接受整数或切片。这是
    import pandas as pd
    stuff = pd.Series(['a','b','a','c','a','d'])
    less_stuff = stuff[stuff != 'a']  # define any condition here
    # results ['b','c','d']
    
    import random
    
    N = 16 * 1024
    x = range(N)
    random.shuffle(x)
    y = random.sample(range(N), N / 10)
    
    def list_set(value_list, index_list):
        index_list = set(index_list)
        result = [value for index, value in enumerate(value_list) if index not in index_list]
        return result
    
    def list_del(value_list, index_list):
        for index in sorted(index_list, reverse=True):
            del(value_list[index])
    
    def list_pop(value_list, index_list):
        for index in sorted(index_list, reverse=True):
            value_list.pop(index)
    
    import timeit
    from collections import OrderedDict
    
    M = 1000
    setup = 'from __main__ import x, y, list_set, list_del, list_pop'
    statement_dict = OrderedDict([
        ('overhead',  'a = x[:]'),
        ('set', 'a = x[:]; list_set(a, y)'),
        ('del', 'a = x[:]; list_del(a, y)'),
        ('pop', 'a = x[:]; list_pop(a, y)'),
    ])
    
    overhead = None
    result_dict = OrderedDict()
    for name, statement in statement_dict.iteritems():
        result = timeit.timeit(statement, number=M, setup=setup)
        if overhead is None:
            overhead = result
        else:
            result = result - overhead
            result_dict[name] = result
    
    for name, result in result_dict.iteritems():
        print "%s = %7.3f" % (name, result)
    
    set =   1.711
    del =   3.450
    pop =   3.618
    
    l = ['a','b','a','c','a','d']
    to_remove = [1, 3]
    [l[i] for i in range(0, len(l)) if i not in to_remove])
    
    my_list = ['word','yes','no','nice']
    
    c=[b for i,b in enumerate(my_list) if not i in (0,2,3)]
    
    print c
    
    some_list.remove(some_list[max(i, j)])
    
    for i in range(len(yourlist)-1, -1, -1):
        del yourlist(i)
    
    ocean_basin = ['a', 'Atlantic', 'Pacific', 'Indian', 'a', 'a', 'a']
    for i in range(1, (ocean_basin.count('a') + 1)):
        ocean_basin.remove('a')
    print(ocean_basin)
    
    ob = ['a', 'b', 4, 5,'Atlantic', 'Pacific', 'Indian', 'a', 'a', 4, 'a']
    remove = ('a', 'b', 4, 5)
    ob = [i for i in ob if i not in (remove)]
    print(ob)
    
    def multi_delete(the_list, indices):
        assert type(indices) in {set, frozenset}, "indices must be a set or frozenset"
        offset = 0
        for i in range(len(the_list)):
            if i in indices:
                offset += 1
            elif offset:
                the_list[i - offset] = the_list[i]
        if offset:
            del the_list[-offset:]
    
    # Example:
    a = [0, 1, 2, 3, 4, 5, 6, 7]
    multi_delete(a, {1, 2, 4, 6, 7})
    print(a)  # prints [0, 3, 5]
    
    delete_from_somelist = []
    for i in [int(0), int(2)]:
         delete_from_somelist.append(somelist[i])
    for j in delete_from_somelist:
         newlist = somelist.remove(j)
    
    def list_diff(list_a, list_b, verbose=False):
    
        # returns a difference of list_a and list_b,
        # preserving the original order, unlike set-based solutions
    
        # get indices of elements to be excluded from list_a
        excl_ind = [i for i, x in enumerate(list_a) if x in list_b]
        if verbose:
            print(excl_ind)
    
        # filter out the excluded indices, producing a new list 
        new_list = [i for i in list_a if list_a.index(i) not in excl_ind]
        if verbose:
            print(new_list)
    
        return(new_list)
    
    my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'woof']
    # index = [0, 3, 6]
    
    # define excluded names list
    excl_names_list = ['woof', 'c']
    
    list_diff(my_list, excl_names_list)
    >> ['a', 'b', 'd', 'e', 'f']
    
    list_indices = [0, 2]
    original_list = [0, 1, 2, 3]
    new_list = np.delete(original_list, list_indices)
    
    array([1, 3])