2017-01-23 2 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

ОП не указывал, что 'a',' b' и т. Д. Являются строками. Ваше решение работает только на основании предположения, что «список» содержит последовательность последовательностей. – mgilson

+0

@mgilson Yep, обновлено ... –

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

"Sub-петлю" 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 the painter * и один из худших способов, которыми вы можете для решения этой проблемы. – Kasramvd

+0

@ Kasramvd Как так? –

+0

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

1

Это будет работать независимо от того, является ли, Ь, с и 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)] 

Вы могли бы хотеть раскомментировать, если заявление (и отступ строки внизу), чтобы проверить, если списки имеют одинаковую длину, в противном случае new_lst будет содержать только стольких элементов, как короткий список.

This, this и the 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'] 
Смежные вопросы