Arrays 在Ruby中将数组解构为数组
假设我有两个相当大的数组,Arrays 在Ruby中将数组解构为数组,arrays,ruby,memory,Arrays,Ruby,Memory,假设我有两个相当大的数组,a和b 我想要b=a+b,但我并不真的需要a,我更愿意保存内存,以避免交换 我考虑过简单地使用: b.unshift( *a.slice!(0..-1) ) 但上述方法的缺点是在程序完成之前仍保留a的副本。另一种选择是: while ! a.empty?() do b.unshift( a.pop() ) end 虽然不够优雅,甚至可能更慢(这是迭代,我不知道*操作符的工作速度有多快,可能是在较低的级别),但这将中间内存占用保持在最小 有更优雅的吗
a
和b
我想要b=a+b
,但我并不真的需要a
,我更愿意保存内存,以避免交换
我考虑过简单地使用:
b.unshift( *a.slice!(0..-1) )
但上述方法的缺点是在程序完成之前仍保留a
的副本。另一种选择是:
while ! a.empty?() do
b.unshift( a.pop() )
end
虽然不够优雅,甚至可能更慢(这是迭代,我不知道*
操作符的工作速度有多快,可能是在较低的级别),但这将中间内存占用保持在最小
有更优雅的吗
有更优雅的吗
同时使用unshift
和pop
:
a = [1,2,3]
b = [4,5,6]
b.unshift(*a.pop(a.size))
p a, b
# []
# [1, 2, 3, 4, 5, 6]
或者如果您不想使用*
:
a = [1,2,3]
b = [4,5,6]
b.unshift(a.pop(a.size)).flatten!
p a, b
# []
# [1, 2, 3, 4, 5, 6]
不能保证分配给
a
的内存会因为删除了所有元素而释放。大多数动态阵列系统都会随着阵列大小的增加进行分配,这是一个很难做到的必要条件,但当涉及到减小大小时,会更加轻松
最好的方法是执行b+=a
,让a
超出范围,然后让垃圾收集器对其进行排序
除非您能够生成一个具体的基准测试,表明您的复杂方法工作得更好,但由于splat操作将创建需要收集的额外垃圾,因此可能不会这样做,否则您应该做最简单的工作。关于
b=a.concat(b)呢
?当您逐个添加元素时,您如何知道ruby不会分配一个的N个副本(从而浪费内存)?如果您确实关心内存,则需要对代码进行内存配置,并查看每个变量分配了多少对象。@Stefan那么它将是b=a.concat(b);a=[]
与b.unshift(*a)相同;a=[]
。我相信这不是@user1134991所要求的。这可能会比最初的尝试产生更多的垃圾,所以请注意。@tadman“可能”?你不太明白这是怎么回事,是吗?来,让我给你解释一下a.pop(a.size)
将返回整个数组a
,还将从数组a
中删除所有元素。内存的变化是由Ruby的实现决定的。答案中描述的两种变体在使用默认Ruby时都完全释放了arraya
的内存。这“可能”不是你应该向任何人解释的方式,特别是那些回答了数千个Ruby问题的人。我之所以这么说,可能是因为不同的实现,甚至不同版本的Ruby在如何处理这一问题上都存在差异,但这绝不是一个保证“更好”的解决方案。内存分析这些代码片段和OP的代码片段将有助于说服读者,这有时确实表现得更好。乍一看,这两个代码段至少分配了一个新的a.size
数组。与问题中的代码大致相同。我认为concat
和unshift
都知道新数组的长度。他们都使用RARRAY_LEN()
来计算,有时MRI根本不会释放任何内存(它的堆只会增长,永远不会缩小)。我想现在好多了。:)@SergioTulentsev啊,1.8天,我们不得不从后面把它们射出去,因为它们太胖太老了。是不是只有1.8天?我的记忆很模糊,但我很确定1.9也是这样运行的。@SergioTulentsev 1.8太糟糕了,以至于存在“EnterpriseRuby”来解决这个问题。1.9有了很大的改进,2.0有了很大的改进。