如何使用列表推导将列表中的第一个 n 奇数加倍?
这是我的解决方案:
>>> n = 2
>>> lst = [1, 2, 3, 4, 5, 6]
>>> lst = [num for num in lst if num % 2 == 1] + [num for num in lst if num % 2 == 0]
>>> lst = [num * 2 for num in lst[:n]] + lst[n:]
>>> print(lst)
[2, 6, 5, 2, 4, 6]
您可以看到我不能保持lst
的相同顺序......
更多示例:
n = 2
lst = [2, 2, 2, 2, 1, 2, 3]
output: lst = [2, 2, 2, 2, 2, 2, 6]
答案 0 :(得分:4)
n
数字加倍,如果它是奇数”:由于您不想从原始列表中删除任何项目,因此您无法使用列表推导语法的过滤器(if
之后的for
)。因此,您需要做的只是将您要放入目标列表的项目转换为。
对于索引为x
的元素i
,您的逻辑是这样的:
def transform(x, i, n):
if i < n:
if x % 2 == 1:
return x * 2
return x
所以你可以使用那个确切的函数并在你的列表理解中使用它:
>>> n = 2
>>> lst = [1, 2, 3, 4, 5, 6]
>>> [transform(x, i, n) for i, x in enumerate(lst)]
[2, 2, 3, 4, 5, 6]
当然,您也可以将其内联到列表理解中:
>>> [x * 2 if i < n and x % 2 == 1 else x for i, x in enumerate(lst)]
[2, 2, 3, 4, 5, 6]
n
个奇数:如果你想找到第一个 n个奇数,你就无法解决这个问题。为了解决这个问题,您需要实际记住在浏览列表之前遇到过多少个奇数。这意味着你需要有某种“记忆”。这样的事情不适合列表理解,因为列表理解应该一次转换一个项目而没有副作用。
相反,您只需按照简单的方式执行此操作:
n = 2
lst = [2, 2, 2, 2, 1, 2, 3]
result = []
for x in lst:
if x % 2 == 1 and n > 0:
result.append(x * 2)
n -= 1
else:
result.append(x)
print(result) # [2, 2, 2, 2, 2, 2, 6]
答案 1 :(得分:2)
使用三元运算符。
lst = [1, 2, 3, 4, 5, 6]
lst = [x * 2 if x % 2 == 1 and i <= n else x for i, x in enumerate(lst)]
或
lst[:n] = [x * 2 if x % 2 == 1 else x for x in lst[:n]]
更新:根据加倍首先n
奇数整数的新要求:
lst = [1, 2, 3, 4, 5, 6]
class Doubler:
def __init__(self, n):
self.n = n
def proc(self, x):
if self.n > 0 and x % 2:
self.n -= 1
return 2 * x
return x
# Double first 2 odd elements
d = Doubler(n=2)
res = [d.proc(x) for x in lst]
print(res)
# [2, 2, 6, 4, 5, 6]
答案 2 :(得分:2)
为了实现这一目标,您需要记录您已经看过的奇数。例如,您可以实例化itertools.count
生成器并在每次遇到奇数时将其前进:
from itertools import count
def f(l, n):
odd = count()
return [x * 2 if x % 2 and next(odd) < n else x for x in l]
>>> f([1, 2, 3, 4, 5, 6], 2)
[2, 2, 6, 4, 5, 6]
>>> f([2, 2, 2, 2, 1, 2, 3], 2)
[2, 2, 2, 2, 2, 2, 6]
答案 3 :(得分:1)
以特异性命名事物,并暴露逻辑。
如何使用列表推导将列表中的前n个奇数加倍?
我们有奇数:v for v in l if n%2
。这是一个过滤器。
我们可以使用islice(odds, n)
获取它们中的第一个n
。我们称之为切片,其他语言可能称之为&#34;采取&#34;。并且将它们加倍是每项操作,因此是地图。加入这些操作,我们就会回答您的问题:
[v*2 for v in islice((v for v in l if n%2), n)]
但是,这不是你想要的。问题是特异性;你的问题并没有说明除了第一个n
奇数之外的其他项目,所以我忽略了它们。
那么,如果我们想要复制你的问题未提及的所有项目,该怎么办?这意味着我们有三组:早期赔率,迟到赔率和均衡,所有这些都得到了明显的处理。后者可能是任意混合,而我们知道后期赔率是在早期赔率之后。如您所示,将它们分成各个流是不切实际的,因为这并不能保持它们的相对顺序。
我将再应用一些itertools函数来解决这个问题。
from itertools import repeat, chain
oddfactors = chain(repeat(2, n), repeat(1))
outlist = [v*next(oddfactors) if v%2 else v
for v in inlist]
请注意,对于每个奇数项而不是项都会读取迭代器oddfactors
,因为if-else表达式在没有使用的情况下不会对表达式求值。迭代器被消耗,您需要创建另一个迭代器以再次执行工作。
可以将oddfactors
迭代器的创建(以及整个范围)放在列表理解中,但我能想到的第一种方式是难以置信的丑陋:
from itertools import repeat, chain
outlist = [v*next(oddfactors) if v%2 else v
for v,oddfactors in zip(
inlist,
repeat(chain(repeat(2, n), repeat(1)))
)]
这里的技巧是确保我们只创建一次链式迭代器,然后将其提供给每个映射操作。此练习确实无法提供可读性或性能。使用嵌套的理解会使它更清晰,但仍然只有一个迭代器,所以它是一个误导性的黑客。
outlist = [v*next(oddfactors) if v%2 else v
for oddfactors in [chain(repeat(2, n), repeat(1))]
for v in inlist]
答案 4 :(得分:-1)
这个怎么样?
n = 2
lst = [1, 2, 3, 4, 5, 6]
for i in range(n):
lst[i]= lst[i]*2
答案 5 :(得分:-2)
[num if num%2 else 2 * num for list in list]。 num if if b else c将返回a如果b为真,否则为c。