it-swarm.com.de

Werte in einer Liste periodisch ersetzen

Angenommen, ich habe die folgende Liste in Python:

my_list = [10] * 95

Mit n möchte ich alle anderen m-Elemente durch Null in meiner Liste ersetzen, wobei die nächsten n-Elemente erhalten bleiben. 

Wenn zum Beispiel n = 3 und m = 2, möchte ich, dass meine Liste folgendermaßen aussieht:

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

Wenn es nicht perfekt gefüllt werden kann, wie es bei n = 4 und m = 2 der Fall ist, ist es in Ordnung, wenn meine Liste so aussieht:

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

Wie soll ich versuchen, dieses Problem zu lösen?

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

Dies erfordert lediglich m-Zuweisungen, um den Job auszuführen (und m ist wahrscheinlich klein).

Wenn Sie wirklich nur zwei mögliche Werte haben (z. B. 10 und 0), können Sie es noch einfacher machen:

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

Aber das wiederholt sich in Python über den gesamten Bereich von 95, also ist es wahrscheinlich nicht sehr schnell.

Etwas komplexer, aber wahrscheinlich effizienter (besonders für große Listen und große Werte für n und m) wäre dies:

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

Es werden jedoch intern viele Listen erstellt, daher müssen Tests durchgeführt werden, um herauszufinden, ob dies in Ihrem Fall effizient ist. (Bei großen Listen sollte auch der Speicherverbrauch berücksichtigt werden.)

Wenn Sie numpy verwenden können (etwas außerhalb der Frage, aber da sie weit verbreitet ist):

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

Sie können itertools.cycle verwenden, um eine endlose Sequenz von [10, 10, 10, 0, 0] zu erstellen, und dann die ersten 95 Elemente dieser Sequenz mit itertools.islice aufnehmen:

n = 3
m = 2

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

Noch eine andere Möglichkeit, diesmal mit enumerate :

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

Es verwendet die Tatsache, dass False und True in Python gleich 0 und 1 sind (siehe hier ).

Als Bonus funktioniert es auch, wenn die Liste nicht konstant ist:

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

Wenn die Liste Zeichenfolgen enthält, werden diese anstelle von 0 durch eine leere Zeichenfolge ersetzt:

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

Das hat für mich funktioniert:

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

welche Ausgänge:

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

Der Code verwendet n und m und erstellt mithilfe der np.tile-Funktion eine Maske aus Einsen und Nullen, deren Länge mit Ihrer ursprünglichen list übereinstimmt. Danach multiplizieren Sie einfach die Maske mit der Liste und bekommen die Nullen dort, wo Sie sie haben möchten. Es sollte auch flexibel auf unterschiedliche Längen der Liste und eine (fast) beliebige Auswahl von n und m sein.

Wenn Sie möchten, können Sie das Array wieder in eine Liste umwandeln.

6
Shintlor

Wie wäre es damit?

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)

Bearbeiten 

Ich habe herausgefunden, dass der obige Code in einigen Fällen die Länge der Ergebnisliste ändert.

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

Die Länge sollte also irgendwie wiederhergestellt werden.

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)
4
klim
[j for i in [[input_num] * n + [0] * m for x in range(int(num / (m + n)) + 1)][:num] for j in i]

Könnte sein?

Ergebnis

>>> 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]
3
Moonsik Park

numpy kann das auch ganz knapp!

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

Auch in der itertools-Familie können Sie repeat ein gewünschtes Muster auswählen:

Gegeben

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]

Prüfung

assert len(res) == 95

@ Aran-Feys itertools.cycle -Lösung ist jedoch sauberer, da keine Verkettung erforderlich ist.

0
pylang