繁体   English   中英

执行大列表的逐元素复合操作

[英]Performing element-wise compound operations of large list

我正在尝试对大列表(> 10000个元素)中的每个元素执行多项操作。 例如,我的列表L1具有x,y,z坐标

L1 = [[1.23,4.55,5.66],[3.23,-8.55,3.66],[5.73,2.35,55.16]]

我希望将每个元素转换为由三个点中每个点的单个十进制浮点数连接而成的单个字符串。 因此,对于以上列表,我希望创建一个新列表L2

L2 = ['1.24.65.7','3.2-8.63.7','5.72.455.2']

我使用简单的for循环和列表理解尝试了以下两种明显的方法。 两种方法都花了8分钟以上才能运行。 我正在发布此问题,以询问一种更快的方法。

#Method1
final = []
for point in points:
     x,y,z = point[0],point[1],point[2]

     final.append(str(round(x,1))+str(round(y,1))+str(round(z,1)))

#Method2
final = [str(round(i[0],1))+str(round(i[1],1))+str(round(i[2],1)) for i in points]

也许字符串格式化会更快。

final = ["%.1f%.1f%.1f" % tuple(i) for i in points]

或F弦:

final = [f"{x:.1f}{y:.1f}{z:.1f}" for x, y, z in points]

您也可以使用timeit比较该方法。 这是快速了解效率的好点。

在这里,只是代码和答案之间的摘要:

# Import timeit
import timeit

L1 = [[1.23, 4.55, 5.66], [3.23, -8.55, 3.66], [5.73, 2.35, 55.16]]

# Lengthen the list
L1 = L1 * 1000


def method_1(L1):
    def func():
        final = []
        for point in L1:
            x, y, z = point[0], point[1], point[2]

            final.append(str(round(x, 1))+str(round(y, 1))+str(round(z, 1)))
    return func


def method_2(L1):
    def func():
        final = [str(round(i[0], 1))+str(round(i[1], 1)) +
                 str(round(i[2], 1)) for i in L1]
    return func


def sol_1_1(L1):
    def func():
        final = ["%.1f%.1f%.1f" % (x, y, z) for x, y, z in L1]
    return func


def sol_1_2(L1):
    def func():
        final = [f"{x:.1f}{y:.1f}{z:.1f}" for x, y, z in L1]
    return func


def sol_2(L1):
    def func():
        final = [''.join(map(str, (round(e, 1) for e in l))) for l in L1]
    return func


t = timeit.Timer(method_1(L1))
print("Method 1: ", t.timeit(50))

t = timeit.Timer(method_2(L1))
print("Method 2: ", t.timeit(50))

t = timeit.Timer(sol_1_1(L1))
print("Answer 1_1: ", t.timeit(50))

t = timeit.Timer(sol_1_2(L1))
print("Answer 1_2: ", t.timeit(50))

t = timeit.Timer(sol_2(L1))
print("Answer 2: ", t.timeit(50))

输出:

Method 1:  0.5920865
Method 2:  0.6394685
Answer 1_1:  0.15333640000000015
Answer 1_2:  0.20070460000000034
Answer 2:  0.6677959000000002

因此,结果让我们认为@Barmar提供的解决方案是最快的。 希望对您有帮助!

只需四舍五入数字,将它们转换为字符串,然后将它们连接在一起

>>> L1 = [[1.23,4.55,5.66],[3.23,-8.55,3.66],[5.73,2.35,55.16]]
>>> L2 = [''.join(map(str, (round(e, 1) for e in l))) for l in L1]
>>> print (L2)
['1.24.55.7', '3.2-8.63.7', '5.72.455.2']

itertools.starmapstr.format一起使用str.format快一点,但速度str.format

from itertools import starmap
result = [*starmap(("{:.1f}"*3).format,l)]

以下是不同方法的测试代码(在Jupyter Notebook中)。

from itertools import starmap
l = [[1.23,4.55,5.66],[3.23,-8.55,3.66],[5.73,2.35,55.16]] * 10000

%timeit [''.join(map(str, (round(e, 1) for e in sl))) for sl in l]
%timeit ["%.1f%.1f%.1f" % tuple(i) for i in l]
%timeit [f"{x:.1f}{y:.1f}{z:.1f}" for x, y, z in l]
%timeit [("{:.1f}"*3).format(*i) for i in l]
%timeit f=("{:.1f}"*3).format;[f(*i) for i in l]
%timeit [*starmap(("{:.1f}"*3).format,l)]

输出:

116 ms ± 758 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
27.5 ms ± 190 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
37.6 ms ± 236 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
28 ms ± 379 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
27 ms ± 426 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
25.7 ms ± 253 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

另外,请尝试预分配列表:

final = [None] * len(points)

然后,不要执行.append(..) ,而是将其设置在相关索引处。

PS:这是一种预感。 它可能会或可能不会帮助您。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM