定期替换列表中的值

时间:2018-09-25 08:00:46

标签: python list replace

假设我在Python中具有以下列表:

my_list = [10] * 95

鉴于n,我想将列表中的其他所有m元素替换为零,同时保留下一个n元素。

例如,如果n = 3m = 2,我希望我的列表看起来像这样:

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

如果不能像n = 4m = 2那样完美地填充它,那么我的列表看起来像这样就可以了:

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

我应该如何解决这个问题?

8 个答案:

答案 0 :(得分:28)

您可以使用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))

答案 1 :(得分:27)

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可能很小)。

如果您确实只有两个可能的值(例如10和0),则可以做得更简单:

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

但是在Python的整个95范围内进行迭代,因此可能不是很快。

稍微复杂一点但可能更有效(尤其是对于nm的庞大列表和大值):

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

但是它在内部构建了很多列表,因此需要测试以确定这是否对您有效。 (对于大型列表,还应考虑内存消耗。)

如果您可以使用numpy(有点问题,但由于它很普遍):

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

答案 2 :(得分:7)

还有另一种可能性,这次是enumerate

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

它利用了FalseTrue等于Python中的01的事实(请参见here)。

作为奖励,即使列表不是恒定的,它也可以正常工作

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

答案 3 :(得分:6)

这对我有用:

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并使用list函数构造一个长度与您的初始np.tile匹配的一和零掩码。然后,您只需将掩码乘以列表,然后将零设为您想要的位置即可。还应该灵活使用列表的不同长度以及nm的(几乎)任意选择。

如果需要,可以将数组转换回列表。

答案 4 :(得分:4)

怎么样?

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 :(得分:3)

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

答案 6 :(得分:3)

numpy也可以非常简洁地做到这一点!

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

答案 7 :(得分:0)

在itertools系列中,您也可以repeat所需的模式:

给出

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解决方案更干净,因为它不需要链接。