2017-01-23 51 views
8

在列表中创建重复

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) 
+0

@Ekaterina编辑你的问题,包括这段代码,而不是在评论中。 – hfz

回答

10

下面是使用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上的嵌套理解来复制列表中的项目。

+3

OP没有指定'a','b'等是字符串。您的解决方案仅基于“list”包含一系列序列的假设。 – mgilson

+0

@mgilson是的,更新... –

2

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

import numpy as np 
np.repeat(lst, numbers).tolist() 

# ['a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd'] 
+0

请注意,这需要你安装numpy,如果你只是解决这个问题,这是过度杀伤 –

5

嵌套列表理解的工作原理:

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'] 

不完全理想的结果。

4

对于任何对象的一般方法(不仅是字符串)可以生成器表达式中使用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种主要途径的基准。需要注意的是最后一个onley适用于字符串:

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 
1

另一种方式与一个循环做到这一点是:

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'] 
1

如果您不确定列表解析如何工作,

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) 
0

假设两个列表具有相同的长度和第二总是号码的列表,这里是不使用zip溶液或任何进口:

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

result = sum([[lst[i]]*numbers[i] for i in range(len(lst))],[]) 
+0

这是一个* shlemiel画家*算法,你可以用最糟糕的方法之一去解决这个问题。 – Kasramvd

+0

@Kasramvd如何? –

+0

https://www.joelonsoftware.com/2001/12/11/back-to-basics/ – Kasramvd

1

这将不管工作是否一个,b,c和d是变量或字符串:您可能希望取消对if语句(和缩进下方的线),以检查是否列出具有相同的长度

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)] 

,否则new_lst将只包含尽可能多的项目越短名单。

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

1

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

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']