Periodically replacing values in a list

Riley 09/25/2018. 8 answers, 1.903 views
python list replace

Suppose I have the following list in Python:

my_list = [10] * 95

Given n, I want to replace any other m elements with zero in my list, while keeping the next n elements.

For example, if n = 3 and m = 2, I want my list to look like:

[10, 10, 10, 0, 0, 10, 10, 10 ,0, 0, ..., 10, 10, 10 , 0, 0]

If it can't be filled perfectly, as is the case with n = 4 and m = 2, then it's OK if my list looks like this:

[10, 10, 10, 10, 0, 0, ..., 10, 10, 10, 10, 0]

How should I try to solve this problem?

8 Answers


Alfe 09/25/2018.
my_list = [10] * 95
n = 3
m = 2
for i in range(m):
    my_list[n+i::m+n] = [0] * len(my_list[n+i::m+n])

This just needs m assignments to do the job (and m probably is small).

If you really just have two possible values (e. g. 10 and 0), you can do it even simpler:

my_list = [ 10 if i % (n+m) < n else 0 for i in range(95) ]

But that iterates in Python over the whole range of 95, so probably is not very fast.

A bit more complex but probably more efficient (especially for huge lists and large values for n and m) would be this:

my_list = (([ 10 ] * n + [ 0 ] * m) * (95 // (n + m) + 1))[:95]

But it builds internally lots of lists, so its up to tests to find out whether this is efficient in your case. (Also memory consumption should be taken into account for large lists.)

If you can use numpy (a bit off the question, but since it's widespread):

my_list = (np.arange(95) % (n+m) < n) * 10

Aran-Fey 09/25/2018.

You could use itertools.cycle to create an endless sequence of [10, 10, 10, 0, 0] and then take the first 95 elements of that sequence with itertools.islice:

n = 3
m = 2

pattern = [10] * n + [0] * m
my_list = list(itertools.islice(itertools.cycle(pattern), 95))

Eric Duminil 09/25/2018.

Yet another possibility, this time with enumerate:

[x * (i % (n + m) < n) for i, x in enumerate(my_list)]

It uses the fact that False and True are equal to 0 and 1 in Python (see here).

As a bonus, it works fine even if the list isn't constant:

>>> n = 4
>>> m = 2
>>> my_list = range(20)
>>> [x * (i % (n+m) < n) for i, x in enumerate(my_list)]
[0, 1, 2, 3, 0, 0, 6, 7, 8, 9, 0, 0, 12, 13, 14, 15, 0, 0, 18, 19]

If the list contains strings, it replaces them with an empty string instead of 0:

>>> my_list = 'abcdefghijk'
>>> [x * (i % (n+m) < n) for i, x in enumerate(my_list)]
['a', 'b', 'c', 'd', '', '', 'g', 'h', 'i', 'j', '']

Shintlor 09/25/2018.

This worked for me:

list = [10] * 95

n = 4
m = 2

amask = np.tile(np.concatenate((np.ones(n),np.zeros(m))),int((len(list)+1)/(n+m)))[:len(list)]

list = np.asarray(list)*amask

which outputs:

array([10., 10., 10., 10.,  0.,  0., 10., 10., 10., 10.,  0.,  0., 10.,
       10., 10., 10.,  0.,  0., 10., 10., 10., 10.,  0.,  0., 10., 10.,
       10., 10.,  0.,  0., 10., 10., 10., 10.,  0.,  0., 10., 10., 10.,
       10.,  0.,  0., 10., 10., 10., 10.,  0.,  0., 10., 10., 10., 10.,
        0.,  0., 10., 10., 10., 10.,  0.,  0., 10., 10., 10., 10.,  0.,
        0., 10., 10., 10., 10.,  0.,  0., 10., 10., 10., 10.,  0.,  0.,
       10., 10., 10., 10.,  0.,  0., 10., 10., 10., 10.,  0.,  0., 10.,
       10., 10., 10.,  0.])

The code takes n and m and constructs a mask of ones and zeros with a length matching your initial list using the np.tile function. Afterwards you just multiply the mask onto the list and get the zeros where you want them to be. It should also be flexibel to different lengths of the list and an (almost) arbitrary choice of n and m.

You can cast the array back to a list if you want.


klim 09/25/2018.

How about this?

my_list = [10] * 95
n = 3
m = 2

for i in range(n, len(my_list)-1, n+m):
    my_list[i:i+m] = [0]*m

print(my_list)

Edit

I found out that the above code changes the length of resulting list in some cases.

>>> a = [1,2,3]
>>> a[2:4] = [0] * 2
>>> a
[1, 2, 0, 0]

Thus, the length should be restored somehow.

my_list = [10] * 95
cp_list = list(my_list)
n = 3
m = 5

for i in range(n, len(my_list)-1, n+m):
    cp_list[i:i+m] = [0]*m

cp_list = cp_list[:len(my_list)]
print(cp_list)

timgeb 09/25/2018.

numpy can do this pretty concisely, too!

a = np.array(my_list).reshape(-1, n + m)
a[:, n:] = 0
result = a.ravel().tolist()

Moonsik Park 09/25/2018.
[j for i in [[input_num] * n + [0] * m for x in range(int(num / (m + n)) + 1)][:num] for j in i]

Maybe?

Result

>>> num, input_num, m, n=95, 10, 2, 3
>>> [j for i in [[input_num] * n + [0] * m for x in range(int(num / (m + n)) + 1)][:num] for j in i]
[10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 10, 10, 10, 0 , 0, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0]

pylang 10/02/2018.

Also in the itertools family, you can repeat a desired pattern:

Given

import itertools as it


m, n = 2, 3
p = n + 1    

Code

pattern = it.repeat([10] * n + [0] * m)
res = list(it.islice(it.chain.from_iterable(pattern), None, 95))
print(res)
# [10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 0, 0, ... 10, 10, 10, 10, 0, 0]

pattern = it.repeat([10] * p + [0] * m)
res = list(it.islice(it.chain.from_iterable(pattern), None, 95))
print(res)
# [10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 0, 0, ... 10, 10, 10, 10, 0]

Test

assert len(res) == 95

However, @Aran-Fey's itertools.cycle solution is cleaner as it does not require chaining.


HighResolutionMusic.com - Download Hi-Res Songs

1 Ariana Grande

7 Rings flac

Ariana Grande. 2019. Writer: Ariana Grande;Richard Rodgers;TBHits;Njomza;Michael "Mikey" Foster;Kaydence;Tayla Parx;Scootie;Oscar Hammerstein II;Victoria Monét.
2 Alan Walker

Lily flac

Alan Walker. 2018. Writer: Alan Walker;Lars Kristian Rosness;Magnus Bertelsen;K-391;Didrik Handlykken;Marcus Arnbekk.
3 Alec Benjamin

Let Me Down Slowly flac

Alec Benjamin. 2019. Writer: Alec Benjamin;Sir Nolan;Michael Pollack.
4 Alan Walker

Lost Control flac

Alan Walker. 2018. Writer: Alan Walker;Thomas Troelsen;Mood Melodies;Sorana;Fredrik Borch Olsen;Magnus "Magnify" Martinsen.
5 Skylar Grey

Everything I Need flac

Skylar Grey. 2018. Writer: Elliott Taylor;Rupert Gregson-Williams;Skylar Grey.
6 Post Malone

Sunflower flac

Post Malone. 2018. Writer: Carl Rosen;Louis Bell;Billy Walsh;Carter Lang;Swae Lee;Post Malone.
7 Westlife

Hello My Love flac

Westlife. 2019. Writer: Steve Mac;Ed Sheeran.
8 Alan Walker

Different World flac

Alan Walker. 2018. Writer: Shy Nodi;Alan Walker;Fredrik Borch Olsen;James Njie;Marcus Arnbekk;Gunnar Greve Pettersen;K-391;Corsak;Shy Martin;Magnus Bertelsen.
9 Sam Smith

Fire On Fire flac

Sam Smith. 2018. Writer: Steve Mac;Sam Smith.
10 Conor Maynard

Way Back Home (Sam Feldt Edit) flac

Conor Maynard. 2018. Writer: Ji Hye Lee;Shaun.
11 Normani

Dancing With A Stranger flac

Normani. 2019. Writer: Mikkel S. Eriksen;Tor Hermansen;Jimmy Napes;Normani;Sam Smith.
12 Slushii

Never Let You Go flac

Slushii. 2019. Writer: Sofía Reyes;Slushii;Aviella Winder.
13 Skrillex

Face My Fears flac

Skrillex. 2019. Writer: Poo Bear;Skrillex;Utada Hikaru.
14 Alora & Senii

Love U So flac

Alora & Senii. 2019. Writer: Alora & Senii.
15 The Chainsmokers

Hope flac

The Chainsmokers. 2018. Writer: Kate Morgan;Chris Lyon;Alex Pall;Andrew Taggart.
16 Imagine Dragons

Believer flac

Imagine Dragons. 2019. Writer: Dan Reynolds;Lil Wayne;Wayne Sermon;Ben McKee;Daniel Platzman;Robin Fredriksson;Mattias Larsson;Justin Tranter.
17 Alan Walker

I Don't Wanna Go flac

Alan Walker. 2018.
18 Mike Perry

Runaway flac

Mike Perry. 2019. Writer: Andreas Wiman;Dimitri Vangelis;Richard Müller;Sasha Rangas;Stefan Van Leijsen;Mike Perry.
19 Gesaffelstein

Lost In The Fire flac

Gesaffelstein. 2019. Writer: Ahmad Balshe;Nate Donmoyer;Gesaffelstein;DaHeala;The Weeknd.
20 Hozier

Almost (Sweet Music) flac

Hozier. 2019. Writer: Hozier.

Related questions

Hot questions

Language

Popular Tags