【发布时间】:2021-01-24 03:48:35
【问题描述】:
例如,我有一个list(也可以是numpy.array 或其他任何东西,我只是想知道一种更快的方法,我不在乎数据类型)['a','b','c','d'],我想得到['ab','bc','cd'].
当然有一个简单的解决方案,例如:
letters = list('abcdefghijk')
my_list = [letters[i:i+2] for i in range(len(letters)-1)]
my_list 是:
[['a', 'b'],
['b', 'c'],
['c', 'd'],
['d', 'e'],
['e', 'f'],
['f', 'g'],
['g', 'h'],
['h', 'i'],
['i', 'j'],
['j', 'k']]
但我想知道是否有更快的方法通过numpy 或其他方式来执行此操作,因为我想使用相对较大的数据来执行此操作,因此简单的for 循环可能会很昂贵。
更新 现在让我总结一下下面的答案。非常感谢@Ehsan 和@Andy L 到目前为止的答案。我通过下面的代码对他们所有的解决方案进行了非常简单的测试,数据相对较大:
import time
import numpy as np
from numba import njit
import matplotlib.pyplot as plt
from numpy.lib.stride_tricks import as_strided
def m1(letters):
return [letters[i]+letters[i+1] for i in range(len(letters)-1)]
@njit
def m2(letters):
return [letters[i]+letters[i+1] for i in range(len(letters)-1)]
def m3(letters):
return np.char.add(letters[:-1], letters[1:])
def m4(letters):
n = len(letters) - 1
m = np.array(letters[0]).itemsize
arr = as_strided(letters, shape=(n, 2), strides=(m, m))
return arr
def test_time(testfunc,args):
start = time.time()
testfunc(*args)
return time.time() - start
# test
ns = [10000, 100000, 1000000, 10000000]
timecost = []
for n in ns:
input_=np.random.choice(list('abcdefghijklmnopqrstuvwxyz'), size=n)
cost = [test_time(testfunc, [input_]) for testfunc in [m1, m2, m3,m4]]
timecost.append(cost)
# result plot
timecost = np.array(timecost)
labels = ['normal','numba.njit','numpy.char.add','numpy.lib.stride_tricks.as_strided']
for i in range(timecost.shape[-1]):
plt.plot(ns, timecost[:, i], label=labels[i])
plt.legend()
plt.savefig('result.png')
结果表明,np.char.add 和numba 在更大数据上的性能确实优于常规方法,但stride_tricks 的性能更好:时间成本降低了两个数量级以上.
【问题讨论】:
-
我不在乎数据类型:它们都是字符吗?或者你的意思是和浮动一样吗?
-
@Ehsan 我的错。我的意思是它们都是字符,但我可以接受任何类型的容器,例如
numpy.array或其他东西。 -
您想要获得
['ab','bc','cd']或[['a', 'b'],['b', 'c'], ['c', 'd'],...吗?这是两种不同的格式。 -
@Divakar
[['a', 'b'],['b', 'c'], ['c', 'd'],...会更好。
标签: python python-3.x numpy