【问题标题】:Multiply every third element of a list by two将列表的每三个元素乘以 2
【发布时间】:2019-10-15 14:26:42
【问题描述】:

输入数据:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
输出数据:[1, 2, 6, 4, 5, 12, 7, 8, 18, 10]

我已经阅读了许多建议使用包含第一个元素的切片表示法的答案。但就我而言,我应该获取列表中的每个第三个元素。

是否有可能提高我的认识?

for index in range(len(data)):
    if (index + 1) % 3 == 0:
        data[index] = data[index] * 2

【问题讨论】:

标签: python list collections iteration list-comprehension


【解决方案1】:

是的,你可以用切片符号来做到这一点:

data[2::3] = [x*2 for x in data[2::3]]

data[2::3] 表示从元素索引 2 开始的每个第三个元素(即第三个元素)。您也可以重新分配回切片,从而实现这种非常简洁的语法。

【讨论】:

  • 您可以通过 data[2::3] = (x*2 for x in data[2::3]) 来改进这一点。这使用了一个生成器,并避免了创建一个临时列表。
  • @TomKarzes 但data[2::3] 本身是一个临时列表。要真正避免创建临时列表,应使用data[2::3] = (x * 2 for x in itertools.islice(data, 2, None, 3))
  • @blhsing 哦,好点。我只是在看“外部”临时列表。我想你也可以data[2::3] = (data[i]*2 for i in range(2, len(data), 3))
  • 实际上,list slice assignment 无论如何都会将materialize 生成器添加到一个列表中,正如我从this answer 的最终评论中了解到的那样
【解决方案2】:

range 迭代器上有一个“step”参数:

for index in range(2, len(data), 3):
    data[index] *= 2

这样可以吗?

【讨论】:

    【解决方案3】:

    您的解决方案还不错。它可以通过简单地直接迭代所需的索引来改进,而不是迭代所有索引并跳过你不想要的索引:

    for index in range(2, len(data), 3):
        data[index] *= 2
    

    这会产生预期的结果:

    [1, 2, 6, 4, 5, 12, 7, 8, 18, 10]
    

    【讨论】:

      【解决方案4】:

      您可以使用 itertools 和 zip 中的循环将项目与其乘数配对:

      data   = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      
      from itertools import cycle
      result = [n*m for n,m in zip(data,cycle([1,1,2]))]
      
      # [1, 2, 6, 4, 5, 12, 7, 8, 18, 10]
      

      或者,你可以使用 enumerate()

      result = [ n*max(1,i%3) for i,n in enumerate(data) ]
      

      【讨论】:

        【解决方案5】:

        您可以通过将第三个参数传递给 range() 函数来稍微组织一下,如下所示:

        for index in range(2, len(data), 3): data[index] = data[index]*2

        【讨论】:

          【解决方案6】:

          ...获胜者是:

          Calculation time in seconds and results validation test.
          1.150 question_by_akrapovich
          0.331 answer_by_Tom_Karzes_and_Prune
          0.333 answer_2_by_Manuel_Montoya
          0.373 answer_by_Blorgbeard
          0.816 answer_1_by_Alain_T
          2.850 answer_2_by_Alain_T
          

          时间测试和结果验证的组合代码:

          import time
          
          
          def question_by_akrapovich(data):
              for index in range(len(data)):
                  if (index + 1) % 3 == 0:
                      data[index] = data[index] * 2
              return data
          
          
          def answer_by_Tom_Karzes_and_Prune(data):
              for index in range(2, len(data), 3):
                  data[index] *= 2
              return data
          
          
          def answer_by_Blorgbeard(data):
              data[2::3] = [x*2 for x in data[2::3]]
              return data
          
          
          def answer_1_by_Alain_T(data):
              from itertools import cycle
              return [n * m for n, m in zip(data, cycle([1, 1, 2]))]
          
          
          def answer_2_by_Alain_T(data):
              return [ n*max(1,i%3) for i,n in enumerate(data) ]
          
          
          def answer_2_by_Manuel_Montoya(data):
              for index in range(2, len(data), 3):
                  data[index] = data[index]*2
              return  data
          
          def test(f):
              n = 10_000_000
              data = [i + 1 for i in range(n)]
              start_time = time.perf_counter()
              data = f(data)
              run_time = time.perf_counter() - start_time
              if n != len(data):
                  print('error in list length', n, len(data))
                  exit(1)
              for i in range(n):
                  j = i + 1
                  m = j * 2 if j % 3 == 0 else j
                  if data[i] != m:
                      print('error in data', i, m, data[i])
                      exit(1)
              print('%.3f %s' % (run_time, f.__name__))
          
          
          print('Calculation time in seconds and results validation test.')
          for f in [question_by_akrapovich, answer_by_Tom_Karzes_and_Prune,
                    answer_2_by_Manuel_Montoya, answer_by_Blorgbeard,
                    answer_1_by_Alain_T, answer_2_by_Alain_T]:
              test(f)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-05-23
            • 2023-03-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-08-14
            相关资源
            最近更新 更多