2

The idea is to repeat list's elements with each different n times as below.

ls = [7, 3, 11, 5, 2, 3, 4, 4, 2, 3]
id_list_fname = ['S11', 'S15', 'S16', 'S17', 'S19', 'S3', 'S4', 'S5', 'S6', 'S9']
all_ls = []
for id, repeat in zip(id_list_fname, ls):
    res = [ele for ele in[id] for i in range(repeat)]
    all_ls.append(res)

Consequently, I would like the result to be a single flat list, which I achieved as below.

def flatten(lst):
    for item in lst:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

final_output = list(flatten(all_ls))

Output of the final_output:

['S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S15', 'S15', 'S15',
 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16',
 'S16', 'S17', 'S17', 'S17', 'S17', 'S17', 'S19', 'S19', 'S3', 'S3',
 'S3', 'S4', 'S4', 'S4', 'S4', 'S5', 'S5', 'S5', 'S5', 'S6', 'S6',
 'S9', 'S9', 'S9']

But I wonder there exist much more compact approach or technique such as itertools to have the repeat elements as what I achieved using the code snippet above.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
mpx
  • 3,081
  • 2
  • 26
  • 56
  • Can you give a minimal example input and desired output? – Iain Shelvington Jan 31 '21 at 06:23
  • Hi @lain, thanks for your interest in this OP. The example input and desired output already provided above. – mpx Jan 31 '21 at 06:25
  • 1
    @balandongiv I do not see the expected output. – yudhiesh Jan 31 '21 at 06:25
  • Hi @yudhiesh, please check the amended version – mpx Jan 31 '21 at 06:28
  • The problem is that `all_ls.append(res)` appends the sub-list of `res` values as a single element, rather than appending all those values separately. For that, `.extend` works, as explained in the first linked duplicate. Otherwise, the trick is to use a nested comprehension to encapsulate the work of the current list comprehension plus the `for id, repeat in zip(id_list_fname, ls):` loop, as in the second linked duplicate. Incidentally, the `ele for ele in[id]` part is useless; the shown list comprehension is equivalent to `[id for i in range(repeat)]`. – Karl Knechtel Oct 04 '22 at 02:07

3 Answers3

6

You can use itertools.chain and itertools.repeat

from itertools import chain, repeat

ls = [7, 3, 11, 5, 2, 3, 4, 4, 2, 3]
id_list_fname = ['S11', 'S15', 'S16', 'S17', 'S19', 'S3', 'S4', 'S5', 'S6', 'S9']
res = list(chain.from_iterable(repeat(j, times = i) for i, j in zip(ls, id_list_fname)))

print(res)

Output

['S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S15', 'S15', 'S15', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S17', 'S17', 'S17', 'S17', 'S17', 'S19', 'S19', 'S3', 'S3', 'S3', 'S4', 'S4', 'S4', 'S4', 'S5', 'S5', 'S5', 'S5', 'S6', 'S6', 'S9', 'S9', 'S9']
python_user
  • 5,375
  • 2
  • 13
  • 32
3

With respect to your code, use list.extend() rather than list.append() when adding items into all_ls. This adds the items in the list to the existing list instead of adding the list to the existing list.

ls = [7, 3, 11, 5, 2, 3, 4, 4, 2, 3]
id_list_fname = ['S11', 'S15', 'S16', 'S17', 'S19', 'S3', 'S4', 'S5', 'S6', 'S9']
all_ls=[]
for s,repeat in zip(id_list_fname ,ls):
    res =  [ele for ele in [s] for i in range(repeat)]
    all_ls.extend(res)

Output

>>> all_ls
['S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S15', 'S15', 'S15', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S17', 'S17', 'S17', 'S17', 'S17', 'S19', 'S19', 'S3', 'S3', 'S3', 'S4', 'S4', 'S4', 'S4', 'S5', 'S5', 'S5', 'S5', 'S6', 'S6', 'S9', 'S9', 'S9']

A better way is with a list comprehension - it can be done in one line:

>>> [item for n,s in zip(ls, id_list_fname) for item in [s]*n]
['S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S11', 'S15', 'S15', 'S15', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S16', 'S17', 'S17', 'S17', 'S17', 'S17', 'S19', 'S19', 'S3', 'S3', 'S3', 'S4', 'S4', 'S4', 'S4', 'S5', 'S5', 'S5', 'S5', 'S6', 'S6', 'S9', 'S9', 'S9']
mhawke
  • 84,695
  • 9
  • 117
  • 138
1

Numpy has the repeat function:

np.repeat(id_list_fname, ls)

If you absolutely need a list:

np.repeat(id_list_fname, ls).tolist()

If you don't want to use numpy, keep in mind that python allows nested comprehensions, which are essentially multiple for loops creating a single flat list. Your original loop can be written as a flat one-liner:

[id for id, repeat in zip(id_list_fname, ls) for _ in range(repeat)]
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264