大阵列上的grep或splice

时间:2011-09-28 04:58:37

标签: perl

我有一大堆哈希值,大约0.5Gb,存储在内存中,我需要从中删除一些元素,大约10%遍布整个数组。

什么更有可能做得最好,做一个grep,或者确定需要删除的元素,并将它们拼接出去?

谢谢,

西蒙

4 个答案:

答案 0 :(得分:5)

基准吗?我猜,不知道你的数据是什么样的,grep会比多次调用具有大量元素的数组更快。

答案 1 :(得分:2)

如果您知道要保持的元素,那么您只需使用数组切片对其进行索引:

@want = @all[ @wanted ];

@all = @all[ @wanted ];

至于grep和splice中的哪一个是最快的,splice将是最快的,因为它需要做的就是在C中移动一些指针,并删除你不再从内存中保留的东西,grep需要更多的工作,因为它需要为原始列表的每个成员调用您的选择函数。

答案 2 :(得分:0)

如果你已经知道你有兴趣删除哪些元素,那么它将更快地定义,因为你不必搜索它们,只删除它们。否则,grep是您快速过滤方法的最佳选择。

答案 3 :(得分:0)

splice可能会在您描述的条件下转到O(n ^ 2)(因为它会移动数组内容),而grep / slice会分配O(n)额外内存(可能很多)小于500GB,但仍然......)。

虽然有一个没有额外内存的线性解决方案,但看起来更像C,而不像Perl:

sub inplace_grep {
    my ($code, $array) = @_; 
    # move elements backwards
    for (my ($to, $from)=(0,0); $from < @$array; $from++) {
        $code->($array->[$from]) or next;
        $array->[$to++] = $array->[$from];
    };
    # remove tail 
    splice @$array, $to; 
};
关于grep内存使用的

更新: - 您可以通过使用大量数据并查找brk系统调用来快速测试额外的内存分配。在我的系统(linux,perl 5.10)上它确实如此。

strace -e trace=brk perl -MTime::HiRes -wle \
'print "start ".time; my @array = 1..10**7; print "alloc ".time;
@array = grep { $_ %2 } @array; print "grep ".time'