社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

python使数组变平,为什么funtools比较慢?

Tommy Yu • 4 年前 • 1041 次点击  

基于这个问题 python flatten an array of array

我想要一个比双循环解决方案更快的方法。所以我写了一个基于functools的函数,但是它看起来慢得多。

orders2.shape
(9966, 1)

import time

t0 = time.time()
[x for i in orders2.values.tolist() for x in i[0].tolist()]
t1 = time.time()

t1-t0
0.009984493255615234
import time

t0 = time.time()
functools.reduce(lambda a,b: a+b[0].tolist() , orders2.values.tolist(), [])
t1 = time.time()

t1-t0
1.4101920127868652

我的问题是1。怎么会这样?2.在使用大数据时,functools算法会比双循环算法快吗?3.还有比双循环更快的算法吗?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/46543
 
1041 次点击  
文章 [ 3 ]  |  最新文章 4 年前
Sraw
Reply   •   1 楼
Sraw    4 年前

我认为至少有两个问题:

  1. 对于第一个列表,您将创建一个列表并在其中附加元素。但是对于第二个列表,您将通过 a+b[0].tolist() ,这将生成一个新列表。

  2. functools.reduce 返回一个发电机,这是主要目的。简而言之,这不是为了速度。

Jab
Reply   •   2 楼
Jab    4 年前

这与 list comprehension vs map 当你使用 lambda 和你的 reduce 语句发送python代码以在每次迭代中运行,从而减慢reduce的速度。列表理解的目的是更有效和可读性,因此它们是首选的方法。

那就是为什么不用 itertools.chain.from_iterable 以及 map 发出砰的声响 operator.itemgetter 是的。这会产生相同的输出,同时也会利用一些很好的内置方法。 没有测试速度

>>> from itertools import chain
>>> from operator import itemgetter
>>> arr = array([[array([33120, 28985,  9327, 45918, 30035, 17794, 40141,  1819, 43668],
      dtype='int64')],
       [array([33754, 24838, 17704, 21903, 17668, 46667, 17461, 32665],
      dtype='int64')],
       [array([46842, 26434, 39758, 27761, 10054, 21351, 22598, 34862, 40285,
       17616, 25146, 32645, 41276], dtype='int64')],
       [array([24534,  8230, 14267,  9352,  3543, 29397,   900, 32398, 34262,
       37646, 11930, 37173], dtype='int64')],
       [array([25157], dtype='int64')],
       [array([ 8859, 20850, 19322,  8075], dtype='int64')]], dtype=object)
>>> array(list(chain.from_iterable(map(itemgetter(0),arr.tolist()))))
[33120 28985  9327 45918 30035 17794 40141  1819 43668 33754 24838 17704
 21903 17668 46667 17461 32665 46842 26434 39758 27761 10054 21351 22598
 34862 40285 17616 25146 32645 41276 24534  8230 14267  9352  3543 29397
 900 32398 34262 37646 11930 37173 25157  8859 20850 19322  8075]
jsbueno
Reply   •   3 楼
jsbueno    4 年前

简而言之,函数调用和列表重新分配的开销是分开的,使用嵌套循环的算法是o(n),使用reduce的算法是o(n)。

即使算法没有什么不同,调用一个函数有“0”代价的想法来自于数学,函数是很好的理论构造。

在计算机程序中运行时,调用一个函数需要初始化一个上下文——在python中,是用局部变量创建一个frame对象。当您有参数被传递时,它意味着在元组中,参数在函数调用之前被构造,并且在函数体中被反构造(尽管这些步骤可能由实现优化)。

在2嵌套循环方法中,您只需在本机代码中迭代迭代器——尽管理论上,根据python的规范,这也意味着调用一个函数(对象的 __iter__ 方法),在本机代码迭代器的实际实现中通常要快得多。

但这并不能解释你在那里看到的不同。主要的问题是每次练习时 a + b[0].tolist() 在存储器中创建一个新的列表“c”,将“a”的值复制到该列表中,然后将b[0]中的值追加到该列表中。而这个新的列表+已经展平的元素的副本将在每个步骤中进行。在list comphrehension情况下,不会发生多余的复制-在展开父2d结构时放置新元素,python经过优化,可以预先分配空间,以供构建时生成的列表使用。