如何在列表/数组中复制特定的值?

7

有什么建议可以在Python中重复数组中的某个值吗? 例如,我想仅重复array_a中的2:

array_a = [1, 2, 1, 2, 1, 1, 2]

希望的结果是:我重复每个2并保留1
array_a = [1, 2, 2, 1, 2, 2, 1, 1, 2, 2]  # only the `2` should be repeated

我尝试使用 numpy ,我可以复制整个数组,但无法复制特定的值。

1
我建议您选择适合当前学习水平的列表操作教程。有许多种方法可以做到这一点,但是您提出问题的方式表明您会从更广泛的主题介绍中受益。教程级别的教育超出了Stack Overflow的范围。 - Prune
由于 OP 尝试使用 numpy 解决问题,因此添加了 numpy 标签。 - cs95
9个回答

4

如果您对numpy解决方案感兴趣,可以使用np.repeat将数组重复自身。

>>> import numpy as np
>>> np.repeat(array_a, array_a)
array([1, 2, 2, 1, 2, 2, 1, 1, 2, 2])

这只适用于数据中只有1和2的情况。如果想要通用解决方案,请考虑:
>>> n_repeats = 2
>>> temp = np.where(np.array(array_a) == 2, n_repeats, 1)
>>> np.repeat(array_a, temp)
array([1, 2, 2, 1, 2, 2, 1, 1, 2, 2])

2
像往常一样,太棒了! - Khalil Al Hooti

3

你可以使用字典来记录每个唯一元素以及它需要重复的次数。然后使用列表推导式来创建数组:

array_a = [1,2,1,2,1,1,2]

repeat_times = {1:1, 2:2} # 1 is 1 time and 2 is repeated two times

result = [i for i in array_a for j in range(repeat_times[i])]
print(result) 

输出:

[1, 2, 2, 1, 2, 2, 1, 1, 2, 2]

不错的方法。风格提示:像 j 这样的虚拟变量使用 _ - Denziloe

1
如果您将此转换为列表,就可以循环遍历它,如果符合您的条件,则添加一个额外版本。例如:
a = [1,2,1,2,1,1,2]
long_a = []
for x in a:
    long_a.append(x)
    if x == 2:
       long_a.append(x)

不错的解决方案--不过调用list是不必要的。 - Denziloe

1
这似乎是一个很好的使用案例,可以使用生成器
>>> def repeater(iterable, repeat_map):
...     for value in iterable:
...         for i in range(repeat_map.get(value, 1)):
...             yield value
...             
>>> array_a = [1,2,1,2,1,1,2]
>>> list(repeater(array_a, repeat_map={2: 2}))
[1, 2, 2, 1, 2, 2, 1, 1, 2, 2]

0

尝试使用推导式。

array = [1, 2, 1, 2, 1, 1, 2]

element_to_repeat = 2

result = [
    repeats_element
    for repeats in
        ((element,)*2 if element == element_to_repeat else (element,) for element in array)
    for repeats_element in repeats
]

它基本上会输出元组,即“重复项”,如果它不是要重复的元素,则包含该元素一次,否则包含两次。然后将这些“重复项”元组的所有元素展开到答案中。

奇怪的负投票,与一个赞同的答案一样。 - Denziloe

0

这里有一个方便的一行代码,使用itertools和包含if和else的列表推导式。首先它创建了一个嵌套列表(以具有在特定位置重复项目的能力),然后最后使用.chain()方法简单地将其展平:

from itertools import chain
array_a = [1, 2, 1, 2, 1, 1, 2]

list(chain.from_iterable([[item, item] if item == 2 else [item] for item in array_a]))
[1, 2, 2, 1, 2, 2, 1, 1, 2, 2]  # output

要加倍的特定值在 if 语句内。使用乘数(而不是 [item, item])和变量(而不是 2)可以使它更通用,例如:

from itertools import chain

def repeat_certain_value(array, val, n):
    return list(chain.from_iterable(([i] * n if i == val else [i] for i in array)))

repeat_certain_value([1, 2, 1, 2, 1, 1, 2], 2, 2)
[1, 2, 2, 1, 2, 2, 1, 1, 2, 2]  # output

repeat_certain_value([0, -3, 1], -3, 5)
[0, -3, -3, -3, -3, -3, 1]  # output

虽然这种方法使用内置库是一个方便的一行代码,但coldspeed的方法更快:

%timeit for x in range(1000): repeat_certain_value([1, 1, 1, 2, 2, 2, 3, 3, 3] * 100, 2, 2)
10 loops, best of 3: 165 ms per loop

%timeit for x in range(1000): coldspeeds_solution([1, 1, 1, 2, 2, 2, 3, 3, 3] * 100, 2, 2)
10 loops, best of 3: 100 ms per loop

0

使用生成器。

array = [1, 2, 1, 2, 1, 1, 2]

element_to_repeat = 2

def add_repeats(array, element_to_repeat):
    for element in array:
        if element == element_to_repeat:
            yield element
            yield element
        else:
            yield element

result = list(add_repeats(array, element_to_repeat))

0
可以尝试使用列表推导式并创建一个名为flat的函数:
array_a = [1, 2, 1, 2, 1, 1, 2]
def flat(l):
   newl=[]
   for i in l:
      if isinstance(i,list):
         newl.extend(i)
      else:
         newl.append(i)
   return newl
print(flat([[i]*2 if i==2 else i for i in array_a]))

输出:

[1, 2, 2, 1, 2, 2, 1, 1, 2, 2]

0

这会不会覆盖匹配位置后面的数字?我应该增加数组大小,然后移位,再添加元素吗? - As tudent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接