首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python - [k] *n上用于列表生成的变体

Python - [k] *n上用于列表生成的变体
EN

Stack Overflow用户
提问于 2016-02-06 10:44:03
回答 5查看 291关注 0票数 2

给定一个元素列表( [1,27,10,...] ),我需要生成每个元素的n重复列表,如‘1,1,.,1,27,27,.,27,10,.,10’。

做这件事最优雅、最浪漫、最快捷的方法是什么?

答案

numpy是最快、最简洁的解决方案。

np.repeat(my_list, n)看上去很像pythonic (归功于B.M.),而扁平化的numpy数组看起来要快得多。

还请看一下B.M.的文章中的numba alternative

更详细的

我测试了三种方法:一是双循环,二是带有索引功能的单循环;三是扁平numpy数组。(编辑:迈克使用extend__的第4种方法,B.M.使用np.repeat的第5种方法,gsb-eng的第6种方法理解,第7种方法迭代工具)

令人惊讶的是,我发现扁平数组是是我的机器上在python2.7中最快的方法。但是,在某些机器和Python 3中,您可能需要测试迭代工具和理解。您可以复制/粘贴下面的Python2代码以进行快速检查,排序后的timeit结果如下:

代码语言:javascript
复制
Flattened array: 8.8ms
Numpy Repeat: 10.87ms
Extend List: 14.37ms
Itertools Repeat: 14.91ms
Itertools  Chain Comprehension: 18.72ms
Itertools Chain: 18.73ms
Double Loop : 58.4ms
Single Loop + index by division: 251.29ms
Double Loop + comprehension: 255.76ms

这是生成结果的代码:

代码语言:javascript
复制
import numpy as np

import timeit

n = 100

my_list = range(10)
n_elements = len(my_list)

# === Double Loop =============================================================
def double_loop():
    my_long_list = []

    for list_element in my_list:
        my_long_list += [list_element] * n

    return my_long_list

# === Double Loop with Comprehension =========================================================    
def double_loop_comp():

    # List comprehension
    return [i for i in my_list for j in xrange(n)]   

# === Single Loop with Indexing Function ======================================
def one_loop_with_indexing():
    my_long_list = []

    for i in range(n*n_elements):
        my_long_list.append(my_list[i // n]) 


    return my_long_list

# === Flattened Array =========================================================
def flattened_array():
    my_array = np.zeros([n_elements, n])

    for i in range(n_elements):
        my_array[i,:] = my_list[i]

    return my_array.flatten()

# === Extend List =========================================================
def extend_list():
    my_long_list = []
    for list_element in my_list:
        my_long_list.extend([list_element] * n)
    return my_long_list

# === Numpy Repeat =========================================================
def numpy_repeat():
    return np.repeat(my_list, n)

# === Itertools Repeat ========================================================
def iter_repeat():
    my_long_list = []
    for x in my_list:
        my_long_list.extend( itertools.repeat(x,n) )
    return my_long_list

# === Itertools Chain =========================================================
def iter_chain():
    return list( itertools.chain.from_iterable( itertools.repeat(x,n) for x in my_list ) )

# === Itertools Chain Comp ====================================================
def iter_chain_comp():
    return list( itertools.chain.from_iterable( [itertools.repeat(x,n) for x in my_list] ) )



time_double_loop = timeit.timeit(double_loop, number=1000)
time_double_loop_comp = timeit.timeit(double_loop_comp, number=1000)
time_single_loop = timeit.timeit(one_loop_with_indexing, number=1000)
time_flattened_array = timeit.timeit(flattened_array, number=1000)
time_extend_list = timeit.timeit(extend_list, number=1000)
time_np_repeat = timeit.timeit(numpy_repeat, number=1000)
time_it_repeat = timeit.timeit(iter_repeat, number=1000)
time_it_chain = timeit.timeit(iter_chain, number=1000)
time_it_chain_comp = timeit.timeit(iter_chain_comp, number=1000)

print 'Double Loop : ' + str(round(time_double_loop*1000,2))+'ms'
print 'Double Loop + comprehension: ' + str(round(time_double_loop_comp*1000,2))+'ms'
print 'Single Loop + index by division: ' + str(round(time_single_loop*1000,2))+'ms'
print 'Flattened array: ' + str(round(time_flattened_array*1000,2))+'ms'
print 'Extend List: ' + str(round(time_extend_list*1000,2))+'ms'
print 'Numpy Repeat: ' + str(round(time_np_repeat*1000,2))+'ms'
print 'Itertools Repeat: ' + str(round(time_it_repeat*1000,2))+'ms'
print 'Itertools Chain: ' + str(round(time_it_chain*1000,2))+'ms'
print 'Itertools  Chain Comprehension: ' + str(round(time_it_chain_comp*1000,2))+'ms'
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2016-02-06 14:45:18

在fast类别中,使用a=np.array(my_list) (测试中的100个元素):

可读性:

代码语言:javascript
复制
In [12]: %timeit np.repeat(a,100)
10000 loops, best of 3: 80.4 µs per loop

棘手的:

代码语言:javascript
复制
In [13]: %timeit np.lib.stride_tricks.as_strided(a,(100,100),(a.itemsize,0)).ravel()
10000 loops, best of 3: 29.5 µs per loop

与numba的及时对比(conda install numba后)

代码语言:javascript
复制
from numba import jit

@jit 
def numbarep(a,n):
    res=np.empty(a.size*n,dtype=a.dtype)
    offset=0
    for e in a:
        for k in range(offset,offset+n):
            res[k]=e
        offset+=n
    return res


In [14]: %timeit numbarep(a,100)
100000 loops, best of 3: 14.8 µs per loop 
票数 1
EN

Stack Overflow用户

发布于 2016-02-06 11:10:04

我把flatten array换成了本地的list comprehension..。

代码语言:javascript
复制
[i for i in my_list for j in xrange(n)]

这是一个更pythonic的方法来解决这种情况.

下面是相同的timeit结果。

代码语言:javascript
复制
Double Loop :0.0249750614166
Single Loop + indexing function: 0.198489904404
List comprehension: 0.00534200668335

下面是在代码中添加list comprehension条目后的完整代码。

代码语言:javascript
复制
import timeit

n = 100

my_list = range(10)
n_elements = len(my_list)

# === Double Loop =============================================================
def double_loop():
    my_long_list = []

    for list_element in my_list:
        my_long_list += [list_element] * n

    return my_long_list

def double_loop_comp():

    # List comprehension
    return [i for i in my_list for j in xrange(n)]

# === Single Loop with Indexing Function ======================================
def one_loop_with_indexing():
    my_long_list = []

    for i in range(n*n_elements):
        my_long_list.append(my_list[i / n])  # !! This would not work if you use "from __future__ import division"


    return my_long_list


time_double_loop = timeit.timeit(double_loop, number=1000)
time_single_loop = timeit.timeit(one_loop_with_indexing, number=1000)
time_double_loop_comp = timeit.timeit(double_loop_comp, number=1000)

print 'Double Loop :' + str(time_double_loop)
print 'Single Loop + indexing function: ' + str(time_single_loop)
print 'List comprehension: ' + str(time_double_loop_comp)
票数 3
EN

Stack Overflow用户

发布于 2016-02-06 10:58:12

您可以使用extend()

代码语言:javascript
复制
def extend_list():
    my_long_list = []
    for list_element in my_list:
        my_long_list.extend([list_element] * n)
    return my_long_list

在我的机器上它更快:

代码语言:javascript
复制
Double Loop :0.0226180553436
Single Loop + indexing function: 0.300093889236
Flattened array: 0.0395331382751
Extend List: 0.0189819335938

列出正确结果的理解:

代码语言:javascript
复制
def double_loop_comp():
    return [i for i in my_list for j in xrange(n)]

列表理解速度较慢:

代码语言:javascript
复制
Double Loop :0.016893863678
Single Loop + indexing function: 0.300258874893
Flattened array: 0.0327677726746
Extend List: 0.0180258750916
Comp: 0.0602869987488
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35240074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档