【问题标题】:Create list of single item repeated N times创建重复N次的单项列表
【发布时间】:2011-03-28 09:50:08
【问题描述】:

我想创建一系列长度不一的列表。每个列表将包含相同的元素e,重复n 次(其中n = 列表的长度)。

如何在不为每个列表使用列表理解 [e for number in xrange(n)] 的情况下创建列表?

【问题讨论】:

    标签: python list-comprehension multiplication replicate


    【解决方案1】:

    你也可以写:

    [e] * n
    

    您应该注意,例如,如果 e 是一个空列表,您会得到一个包含 n 个对同一列表的引用的列表,而不是 n 个独立的空列表。

    性能测试

    乍一看,似乎重复是创建具有 n 个相同元素的列表的最快方法:

    >>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
    0.37095273281943264
    >>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
    0.5577236771712819
    

    但是等等 - 这不是一个公平的测试......

    >>> itertools.repeat(0, 10)
    repeat(0, 10)  # Not a list!!!
    

    itertools.repeat 函数实际上并没有创建列表,它只是创建了一个对象,如果您愿意,可以使用该对象创建一个列表!让我们再试一次,但转换为列表:

    >>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
    1.7508119747063233
    

    因此,如果您想要一个列表,请使用[e] * n。如果要惰性生成元素,请使用repeat

    【讨论】:

    • 创建具有相同元素的列表的性能不太可能成为 Python 程序性能的关键组成部分。
    • 如前所述,如果e为空列表[[]] * n会产生意想不到的结果。要创建 unique empty sub-lists,请使用 for-comprehension:[[] for i in range(0,n)]
    【解决方案2】:
    >>> [5] * 4
    [5, 5, 5, 5]
    

    当重复的项目是一个列表时要小心。该列表不会被克隆:所有元素都将引用同一个列表!

    >>> x=[5]
    >>> y=[x] * 4
    >>> y
    [[5], [5], [5], [5]]
    >>> y[0][0] = 6
    >>> y
    [[6], [6], [6], [6]]
    

    【讨论】:

    • 有意义吗?创建一个列表,然后更改一个元素,整个列表都会更改?
    • @Timo。是的。外部列表存储了对同一个内部列表的四个引用。
    【解决方案3】:

    在 Python 中创建重复 n 次的单项列表

    根据您的用例,您希望使用具有不同语义的不同技术。

    为不可变项乘以一个列表

    对于不可变项,例如 None、bool、int、float、string、tuples 或 freezeset,您可以这样做:

    [e] * 4
    

    请注意,这通常仅用于列表中的不可变项(字符串、元组、frozensets、),因为它们都指向内存中同一位置的同一项。当我必须构建一个包含所有字符串架构的表时,我经常使用它,这样我就不必提供高度冗余的一对一映射。

    schema = ['string'] * len(columns)
    

    将我们希望重复相同项目的列表相乘

    将一个列表相乘会一遍又一遍地为我们提供相同的元素。很少有这种需求:

    [iter(iterable)] * 4
    

    这有时用于将可迭代对象映射到列表列表中:

    >>> iterable = range(12)
    >>> a_list = [iter(iterable)] * 4
    >>> [[next(l) for l in a_list] for i in range(3)]
    [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
    

    我们可以看到a_list 包含四次相同的范围迭代器:

    >>> a_list
    [<range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>]
    

    可变项目

    我已经使用 Python 很长时间了,而且我很少看到使用可变对象执行上述操作的用例。

    相反,要获取可变的空列表、集合或字典,您应该执行以下操作:

    list_of_lists = [[] for _ in columns]
    

    在这种情况下,下划线只是一个一次性的变量名。

    如果你只有数字,那就是:

    list_of_lists = [[] for _ in range(4)]
    

    _ 并不特别,但如果您不打算使用该变量并使用任何其他名称,您的编码环境样式检查器可能会报错。


    对可变项使用不可变方法的注意事项:

    注意对可变对象执行此操作,当您更改其中一个时,它们都会更改,因为它们都是 相同的 对象:

    foo = [[]] * 4
    foo[0].append('x')
    

    foo 现在返回:

    [['x'], ['x'], ['x'], ['x']]
    

    但是对于不可变对象,你可以让它工作,因为你改变的是引用,而不是对象:

    >>> l = [0] * 4
    >>> l[0] += 1
    >>> l
    [1, 0, 0, 0]
    
    >>> l = [frozenset()] * 4
    >>> l[0] |= set('abc')
    >>> l
    [frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]
    

    但同样,可变对象对此没有好处,因为就地操作会更改对象,而不是引用:

    l = [set()] * 4
    >>> l[0] |= set('abc')    
    >>> l
    [set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
    

    【讨论】:

      【解决方案4】:

      Itertools 有一个专门的功能:

      import itertools
      it = itertools.repeat(e,n)
      

      当然itertools 给你一个迭代器而不是一个列表。 [e] * n 为您提供了一个列表,但是,根据您对这些序列的处理方式,itertools 变体可能更有效。

      【讨论】:

        【解决方案5】:

        正如其他人指出的那样,对可变对象使用 * 运算符会重复引用,因此如果您更改一个,则将它们全部更改。如果你想创建一个可变对象的独立实例,你的 xrange 语法是最 Pythonic 的方法。如果您对从未使用过的命名变量感到困扰,您可以使用匿名下划线变量。

        [e for _ in xrange(n)]
        

        【讨论】:

          【解决方案6】:
          [e] * n
          

          应该工作

          【讨论】:

            【解决方案7】:

            如果您正在寻找一个简单的重复,例如:

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

            简单地使用:

            [1, 2, 3] * 3
            

            但如果你正在寻找:

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

            这个更好,但需要更多时间:

            numpy.concatenate([([i]*3) for i in [1,2,3]], axis=0)
            

            【讨论】:

              【解决方案8】:

              对不起,我的回答太晚了 您可以轻松使用numpy.repeat。只需写下您想要生成的值和重复次数即可。

              import numpy as np
              x = [1,2,3]
              y = np.linspace(0,1000,10000)
              for i in x:
                  new_x = np.repeat(i,len(y))
                  print(new_x)
              

              【讨论】:

                猜你喜欢
                • 2021-04-15
                • 2013-05-28
                • 2016-01-07
                • 2020-09-28
                • 1970-01-01
                • 2019-02-16
                • 2020-02-20
                • 2014-08-05
                相关资源
                最近更新 更多