【问题标题】:How to discard an element from a set without rearranging it?如何在不重新排列的情况下丢弃集合中的元素?
【发布时间】:2014-01-08 06:00:37
【问题描述】:

我有一个字符串列表,如果它存在于列表中,我想删除它,所以我将它转换为一个集合并执行此操作

input=set(input)
input.discard('')
input=list(input)

如果“”存在,我可以丢弃它,但我的集合(和列表)正在重新排列。这可以防止吗?

p.s:- 输入是我的列表,我是python的初学者。

【问题讨论】:

  • 套装未订购。您不能依赖具有任何特定顺序的集合中的元素。
  • 集合也丢弃重复的元素。是否要删除重复项以及 ''?

标签: python list set


【解决方案1】:

使用list comprehension

>>> lst = ['a', 'b', '', 'c', '', 'd']
>>> lst = [x for x in lst if x != '']
>>> lst
['a', 'b', 'c', 'd']

【讨论】:

    【解决方案2】:

    使用函数式编程概念:

    >>> my_list = ['hello', 'there', '', 'I', 'try', '', 'to', 'be', 'helpful']
    >>> my_list = filter(lambda a: a != '', my_list)
    >>> my_list
    ['hello', 'there', 'I', 'try', 'to', 'be', 'helpful']
    

    我对各种各样的答案很感兴趣,所以我进行了一些比较。

    import time
    
    num_trials = 1000000
    my_list = ['a', 'b', '', 'c', '', 'd']
    start = time.time()
    for i in xrange(num_trials):
        [x for x in my_list if x != '']
    end = time.time()
    list_comp = (end - start) / num_trials
    
    start = time.time()
    for i in xrange(num_trials):
        filter(lambda a: a != '', ['a', 'b', '', 'c', '', 'd'])
    end = time.time()
    functional = (end - start) / num_trials
    
    print "Over {0} trials...".format(num_trials)
    print "Using list comprehension, the average time to execute was {0}".format(list_comp)
    print "Using filter and lambda, the average time to execute was {0}".format(functional)
    
    #Over 1000000 trials...
    #Using list comprehension, the average time to execute was 2.03965497017e-06
    #Using filter and lambda, the average time to execute was 3.60413718224e-06
    

    因此,列表理解似乎稍微快一些,至少对于我测试的列表而言。

    编辑:我很抱歉!列表推导使用的是预分配列表my_list,而我让 lambda+filter 表达式每次都为一个新列表分配内存!我还对作者接受的答案filter(None, my_list) 进行了测试。该代码如下所示:

    start = time.time()
    for i in xrange(num_trials):
            filter(None, my_list)
    end = time.time()
    filter_none = (end - start) / num_trials
    

    而新的输出是:

    #Over 1000000 trials...
    #Using list comprehension, the average time to execute was 1.80612707138e-06
    #Using filter and lambda, the average time to execute was 2.1211681366e-06
    #Using filter(None), the average time to execute was 1.11886692047e-06
    

    所以,filter(None, some_list) 似乎拿走了蛋糕!

    【讨论】:

    • 有一个 timeit 模型,它为执行时间测量提供了一个方便的包装器。是的,列表理解更快
    • 我尝试使用 timeit 模块,但每个列表理解的执行时间为 2-3 秒!我应该使用timeit.timeit("expression_to_be_evaluated")吗?
    • timeit 为您提供大量迭代的总体时间。在 Ubuntu 的 iPython(可能还有其他 Linux 版本)上,有一个神奇的运算符 %timeit,它可以为您提供纯每个循环的结果。是的,它是 timeit.timeit - 但我有一段时间没有使用它了。虽然它是更精确的形式(显式初始化等)
    • 为了保持一致 - 尝试理解为 [x for x in my_list if x],因为这是使用 filter 的解决方案的工作方式.此外 - lambda 会增加开销。
    【解决方案3】:

    将列表转换为集合不会保留顺序:

    list(set([3, 2, 1]))
    

    产量

    [1, 2, 3]
    

    改为使用for comprehension 过滤您的列表:

    list = [elem for elem in list if n != unwantedElem]
    

    【讨论】:

      【解决方案4】:
      在这种情况下,不应使用

      Set 操作。设置操作将使您的列表元素独一无二。即如果您有两个或多个相同的字符串重复多次,那么重复的字符串将被删除。此处应使用列表推导。这将保留旧的

      >>> a = ['apple', 'orange', '', 'grapes', 'pineapple', '', 'cherry', '']
      >>> [ x for x in a if x != '' ] 
      ['apple', 'orange', 'grapes', 'pineapple', 'cherry']
      

      【讨论】:

        【解决方案5】:

        谢谢大家,但我需要的是

        filter(None, some_list)
        

        找到了

        【讨论】:

        • 这是我测试过的最快的。它也相当 Pythonic!
        • 这很奇怪。我一直认为filter的第一个参数必须是一个函数。
        • 很高兴知道。请注意,这也会从列表中过滤 0、None 和 false。
        猜你喜欢
        • 1970-01-01
        • 2023-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-11
        • 2020-01-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多