我正在尝试执行以下操作
from numpy import *
x = array([[3,2,3],[711,4,104],.........,[4,4,782,7845]]) # large nparray
for item in x:
set(item)
x = array([[3,2,3],[711,4,104],.........,[4,4,782,7845]]) # large nparray
for item in x:
item.tolist()
set 需要更长的时间比到 list ?O(n) ?
最佳答案
TL;DR:set()函数使用 Python 迭代协议(protocol)创建一个集合。但是在 NumPy 数组上迭代(在 Python 级别)太慢以至于使用 tolist()在进行迭代之前将数组转换为 Python 列表会(快得多)。
要理解为什么迭代 NumPy 数组如此缓慢,重要的是要知道 Python 对象、Python 列表和 NumPy 数组是如何存储在内存中的。
Python 对象需要一些簿记属性(如引用计数、指向其类的链接等)以及它所代表的值。例如整数 ten = 10看起来像这样:

蓝色圆圈是您在 Python 解释器中为变量 ten 使用的“名称”。而较低的对象(实例)实际上代表整数(因为簿记属性在这里并不重要,我在图像中忽略了它们)。
一个 Python list只是 Python 对象的集合,例如 mylist = [1, 2, 3]会像这样保存:

这次列表引用了 Python 整数 1 , 2和 3和名称 mylist仅引用 list实例。
但是一个数组 myarray = np.array([1, 2, 3])不将 Python 对象存储为元素:

值 1 , 2和 3直接存储在 NumPy array实例。
有了这些信息,我就可以解释为什么要迭代 array与 list 上的迭代相比要慢得多:
每次访问 list 中的下一个元素时list只返回一个存储的对象。这非常快,因为该元素已经作为 Python 对象存在(它只需要将引用计数加一)。
另一方面,当您想要 array 的元素时在返回之前,它需要为包含所有簿记内容的值创建一个新的 Python“框”。当您遍历数组时,它需要为数组中的每个元素创建一个 Python 框:

创建这些框很慢,主要原因是迭代 NumPy 数组比迭代存储值的 Python 集合(列表/元组/集/字典)慢得多 和他们的盒子 :
import numpy as np
arr = np.arange(100000)
lst = list(range(100000))
def iterateover(obj):
for item in obj:
pass
%timeit iterateover(arr)
# 20.2 ms ± 155 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit iterateover(lst)
# 3.96 ms ± 26.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
set “构造函数”只是对对象进行迭代。tolist方法要快得多。最后,生成的 Python 列表中的每个值都需要位于“Python 框”中,因此 tolist 没有太多工作要做可以避免。但我确定的一件事是 list(array)比 array.tolist() 慢:arr = np.arange(100000)
%timeit list(arr)
# 20 ms ± 114 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit arr.tolist()
# 10.3 ms ± 253 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
O(n)运行时复杂性,但常数因素非常不同。set()至 tolist() - 这不是一个特别好的比较。比较 set(arr) 会更有意义至 list(arr)或 set(arr.tolist())至 arr.tolist() :arr = np.random.randint(0, 1000, (10000, 3))
def tosets(arr):
for line in arr:
set(line)
def tolists(arr):
for line in arr:
list(line)
def tolists_method(arr):
for line in arr:
line.tolist()
def tosets_intermediatelist(arr):
for line in arr:
set(line.tolist())
%timeit tosets(arr)
# 72.2 ms ± 2.68 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit tolists(arr)
# 80.5 ms ± 2.18 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit tolists_method(arr)
# 16.3 ms ± 140 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit tosets_intermediatelist(arr)
# 38.5 ms ± 200 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
set你最好使用 set(arr.tolist()) .对于更大的数组,使用 np.unique 可能是有意义的。但是因为您的行只包含 3 个可能会变慢的项目(对于数千个元素,它可能会快得多!)。set s 但因为它们是输入的,所以它们很可能也避免了“Python 框”并将值直接存储在 set 中。 :
list 更复杂s 因为它们涉及 hash es 和空槽(Python 对集合使用开放寻址,所以我假设 numba 也会)。array numba set直接保存值。所以当你转换一个 NumPy array到 NumPy set (或反之亦然)它根本不需要使用“Python 盒子”,所以当你创建 set 时s in a numba nopython 功能它甚至会比set(arr.tolist())快得多手术:import numba as nb
@nb.njit
def tosets_numba(arr):
for lineno in range(arr.shape[0]):
set(arr[lineno])
tosets_numba(arr) # warmup
%timeit tosets_numba(arr)
# 6.55 ms ± 105 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
set(arr.tolist()) 快五倍方法。但重要的是要强调我没有返回 set s 从函数。当您返回 set从 nopython numba 函数到 Python Numba 创建了一个 python 集合——包括为集合中的所有值“创建盒子”(这是 numba 隐藏的东西)。list,同样的装箱/拆箱会发生s 到 Numba nopython 函数或从这些函数返回列表。那么什么是 O(1) Python 中的操作是 O(n)与 Numba 一起操作!这就是为什么通常最好将 NumPy 数组传递给 numba nopython 函数(即 O(1))。
from numpy import *应该避免,当你这样做时,你隐藏了几个 python 内置函数( sum , min , max ,...),它把很多东西放到你的全局变量中。更好用 import numpy as np . np.在函数调用前面使代码更清晰,不需要输入太多。
关于python - 将 NumPy 数组转换为集合花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44224696/
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat