【问题标题】:Create duplicates in the list在列表中创建重复项
【发布时间】:2017-06-08 05:50:13
【问题描述】:

我有

 list = [a, b, c, d]

numbers = [2, 4, 3, 1]

我想获取以下类型的列表:

new_list = [a, a, b, b, b, b, c, c, c, d]

这是我目前所拥有的:

new_list=[] 
for i in numbers: 
    for x in list: 
        for i in range(1,i+1): 
            new_list.append(x)

【问题讨论】:

  • @Ekaterina 编辑您的问题以包含那段代码,而不是在 cmets 中。

标签: python list


【解决方案1】:

这是使用zip、字符串乘法和列表理解的一种方法:

lst = ['a', 'b', 'c', 'd'] 
numbers = [2 , 4, 3, 1]

r = [x for i, j in zip(lst, numbers) for x in i*j]
print(r)
# ['a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']

使用 Python 时要注意名称的选择。像list 这样的名称会使内置列表函数无法使用。

如果lst 中的项目不是字符串,您可以简单地在range 上使用嵌套推导来复制列表中的项目。

【讨论】:

  • OP 没有指定 ab 等是字符串。您的解决方案仅基于“list”包含一堆序列的假设。
【解决方案2】:

嵌套列表理解有效:

L = ['a','b','c','d']
numbers = [2, 4, 3, 1]

>>> [x for x, number in zip(L, numbers) for _ in range(number)]
['a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']

“子循环”for _ in range(number) 重复值 number 次。 这里L 可以保存任何对象,而不仅仅是字符串。

例子:

L = [[1, 2, 3],'b','c', 'd']
numbers = [2, 4, 3, 1]
[x for x, number in zip(L, numbers) for _ in range(number)]
[[1, 2, 3], [1, 2, 3], 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']

但这会使子列表变平:

[x for i, j in zip(L, numbers) for x in i*j]
[1, 2, 3, 1, 2, 3, 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']

不完全是想要的结果。

【讨论】:

    【解决方案3】:

    作为任何对象(不仅是字符串)的通用方法,您可以在生成器表达式中使用itertools.repeat()

    def repeat_it(lst, numbers):
        return chain.from_iterable(repeat(i, j) for i, j in zip(lst, numbers))
    

    演示:

    In [13]: from itertools import repeat, chain
    
    In [21]: lst=[5,4,6,0]
    
    In [22]: list(repeat_it(lst, numbers))
    Out[22]: [5, 5, 4, 4, 4, 4, 6, 6, 6, 0]
    
    In [23]: lst=['a','b','c','d']
    
    In [24]: list(repeat_it(lst, numbers))
    Out[24]: ['a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']
    

    这里是 3 种主要方法的基准。请注意,最后一个仅适用于字符串:

    In [49]: lst = lst * 1000
    
    In [50]: numbers = numbers * 1000
    
    In [51]: %timeit list(chain.from_iterable(repeat(i, j) for i, j in zip(lst, numbers)))
    1 loops, best of 3: 8.8 s per loop
    
    In [52]: %timeit [x for x, number in zip(lst, numbers) for _ in range(number)]
    1 loops, best of 3: 12.4 s per loop
    
    In [53]: %timeit [x for i, j in zip(lst, numbers) for x in i*j]
    1 loops, best of 3: 7.2 s per loop
    

    【讨论】:

      【解决方案4】:

      您可以使用numpy.repeat() 作为另一个选项:

      import numpy as np
      np.repeat(lst, numbers).tolist()
      
      # ['a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']
      

      【讨论】:

      • 请注意,这需要您安装 numpy,如果您只是解决这个问题,这将是大材小用
      【解决方案5】:

      使用循环的另一种方法是:

      new_list = []
      for number, item in zip(numbers, l):
          for i in range(number):
              new_list.append(item)
      

      现在我们有了:

      new_list = ['a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']
      

      【讨论】:

        【解决方案6】:

        如果您不确定列表推导的工作原理,

        myList=['a','b','c','d'] # not a good idea to use list as a name for your variable
        numbers=[2,4,3,1]
        new_list=[]
        for i in range(len(myList)):     
            for j in range(numbers[i]):          
                new_list.append(myList[i])
        
        print(new_list)
        

        【讨论】:

          【解决方案7】:

          无论 a、b、c 和 d 是变量还是字符串,这都会起作用:

          a = 1
          b = 2.0
          c = "cheese"
          d = ["c", "a", "k", "e"]
          
          lst = [a, b, c, d]
          numbers = [2, 4, 3, 1]
          
          # if len(lst) == len(numbers):
          new_lst = [i for i, j in zip(lst, numbers) for k in range(j)]
          

          您可能需要取消注释 if 语句(并缩进下面的行)以检查列表是否具有相同的长度,否则 new_lst 将仅包含与较短列表一样多的项目。

          Thisthisthe documentation section on nested list comprehensions 值得一读。

          【讨论】:

            【解决方案8】:

            这是我的解决方案,只是添加一个不同的解决方案。

            l = ['a', 'b', 'c', 'd']
            n = [2, 4, 3, 1]
            r = []
            for i,v in enumerate(l):
                r += list(v*n[i])
            
            >>> r
                ['a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd']
            

            【讨论】:

              【解决方案9】:

              假设两个列表的长度相同,第二个总是数字列表,这是一个不使用 zip 或任何导入的解决方案:

              lst = ['a', 'b', 'c', 'd']
              numbers = [2,4,3,1]
              
              result = sum([[lst[i]]*numbers[i] for i in range(len(lst))],[])
              

              【讨论】:

              • 这是一个 shlemiel thepainter 算法,是解决这个问题的最糟糕的方法之一。
              • @Kasramvd 怎么样?
              • @Kasramvd,是的,谢谢,我已经读过了,我想问它在这里如何应用
              猜你喜欢
              • 1970-01-01
              • 2020-07-07
              • 2020-03-17
              • 2018-06-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-03-28
              相关资源
              最近更新 更多