用for循环列表理解

时间:2017-07-29 12:36:48

标签: python python-3.x list-comprehension

如何使用列表推导将列表中的第一个 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]

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。