在Perl中从数组中删除值的最佳方法是什么?

use*_*246 77 arrays perl

该数组有很多数据,我需要删除两个元素.

以下是我正在使用的代码段,

my @array = (1,2,3,4,5,5,6,5,4,9);
my $element_omitted = 5;
@array = grep { $_ != $element_omitted } @array;
Run Code Online (Sandbox Code Playgroud)

Squ*_*Cog 85

如果您已经知道要删除的元素的索引,请使用splice.

如果您正在搜索,Grep可以工作.

如果你需要做很多这些,如果你按照排序的顺序保持你的数组,你将获得更好的性能,因为你可以进行二进制搜索以找到必要的索引.

如果在您的上下文中有意义,您可能需要考虑对已删除的记录使用"魔术值",而不是删除它们,以节省数据移动 - 例如,将已删除的元素设置为undef.当然,这有其自身的问题(如果您需要知道"实时"元素的数量,您需要单独跟踪它等),但根据您的应用程序可能值得一试.

编辑实际上现在我再看看 - 不要使用上面的grep代码.找到要删除的元素的索引会更有效,然后使用splice删除它(你已经累积了所有不匹配的结果的代码..)

my $index = 0;
$index++ until $arr[$index] eq 'foo';
splice(@arr, $index, 1);
Run Code Online (Sandbox Code Playgroud)

这将删除第一次出现.删除所有匹配项非常相似,除非您希望在一次传递中获取所有索引:

my @del_indexes = grep { $arr[$_] eq 'foo' } 0..$#arr;
Run Code Online (Sandbox Code Playgroud)

剩下的作为阅读器的练习 - 请记住,当你拼接它时,阵列会发生变化!

Edit2 John Siracusa正确地指出我的例子中有一个错误..修复,抱歉.

  • 如果找不到字符串,循环将卡住,所以我的$ index = 0; 我的$ count =标量@arr; $ index ++直到$ arr [$ index] eq'foo'或$ index == $ count; splice(@arr,$ index,1); (13认同)
  • 或 `my ($index) = grep { $arr[$_] eq 'foo' } 0..$#arr; if (定义$index) {splice(@arr, $index, 1); }` - 第一场比赛 (2认同)

spo*_*son 13

splice将通过索引删除数组元素.使用grep(如示例所示)进行搜索和删除.


Che*_*tan 12

你可以简单地这样做:

my $input_Color = 'Green';
my @array = qw(Red Blue Green Yellow Black);
@array = grep {!/$input_Color/} @array;
print "@array";
Run Code Online (Sandbox Code Playgroud)


tva*_*son 8

这是你要做的很多事吗?如果是这样,您可能需要考虑不同的数据结构.Grep每次都会搜索整个阵列,对于大型阵列而言,这可能会非常昂贵.如果速度是个问题,那么您可能需要考虑使用Hash.

在您的示例中,键将是数字,值将是该数字的元素数.


小智 5

如果你改变

my @del_indexes = grep { $arr[$_] eq 'foo' } 0..$#arr;
Run Code Online (Sandbox Code Playgroud)

my @del_indexes = reverse(grep { $arr[$_] eq 'foo' } 0..$#arr);
Run Code Online (Sandbox Code Playgroud)

这通过首先从数组的后面删除元素来避免阵列重新编号问题.将splice()放在foreach循环中可以清除@arr.相对简单易读......

foreach $item (@del_indexes) {
   splice (@arr,$item,1);
}
Run Code Online (Sandbox Code Playgroud)


ory*_*unn 5

您可以使用数组切片而不是拼接。Grep 返回要保留的索引并使用切片:

my @arr = ...;
# run through each item.
my @indicesToKeep = grep { $arr[$_] ne 'foo' } 0..$#arr;
@arr = @arr[@indicesToKeep];
Run Code Online (Sandbox Code Playgroud)