web-dev-qa-db-ja.com

リスト内の値を定期的に置き換える

Pythonに次のリストがあるとします。

my_list = [10] * 95

nが与えられた場合、次のm要素を保持しながら、リスト内の他のn要素をゼロに置き換えたいと思います。

たとえば、n = 3およびm = 2の場合、リストは次のようになります。

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

n = 4およびm = 2の場合のように、完全に入力できない場合、リストが次のようであれば問題ありません。

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

この問題を解決するにはどうすればよいですか?

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

これには、ジョブを実行するためにm割り当てが必要です(おそらくmは小さいでしょう)。

本当に2つの可能な値(たとえば、10と0)だけがある場合は、さらに簡単にすることができます。

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

しかし、これは95の範囲全体でPythonで繰り返されるため、おそらくそれほど高速ではありません。

もう少し複雑ですが、おそらくより効率的です(特に、nmの大きなリストと大きな値の場合)。

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

しかし、内部的に多くのリストを作成するため、これがあなたの場合に効率的かどうかを調べるテストまであります。 (大きなリストの場合は、メモリ消費も考慮する必要があります。)

numpyを使用できる場合(質問から少し外れていますが、それは広く普及しているため):

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

itertools.cycle を使用して[10, 10, 10, 0, 0]の無限シーケンスを作成し、 itertools.islice でそのシーケンスの最初の95要素を取得できます。

n = 3
m = 2

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

さらに別の可能性、今度は enumerate

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

FalseTrue01と等しいという事実を使用しますPython(こちらを参照してください こちら )。

ボーナスとして、リストが一定でなくても問題なく機能します。

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

リストに文字列が含まれている場合、0の代わりに空の文字列に置き換えます。

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

これは私のために働いた:

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

どの出力:

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

コードはnmを取り、np.tile関数を使用して、最初のlistと一致する長さの1と0のマスクを作成します。その後、リストにマスクを掛けて、必要な場所にゼロを取得します。また、異なる長さのリストと(ほぼ)任意のnおよびmの任意の長さに柔軟に対応する必要があります。

必要に応じて、配列をリストにキャストできます。

6
Shintlor

これはどう?

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)

編集

上記のコードが結果リストの長さを変更する場合があることがわかりました。

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

したがって、長さは何らかの形で復元する必要があります。

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

多分?

結果

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

numpyもこれを非常に簡潔に行うことができます!

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

また、itertoolsファミリーでは、 repeat 目的のパターンを使用できます。

Given

import itertools as it


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

コード

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]

テスト

assert len(res) == 95

ただし、@ Aran-Feyの itertools.cycle ソリューションは、連鎖を必要としないため、よりクリーンです。

0
pylang