首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从另一个数组中移除特定的数组元素

从另一个数组中移除特定的数组元素
EN

Stack Overflow用户
提问于 2013-09-02 08:13:28
回答 4查看 139关注 0票数 2

问题-我有两个数组如下所示。

代码语言:javascript
复制
my @arr1 = qw( jon won don pon );
my @arr2 = qw( son kon bon won kon don pon won pon don won);

我需要从@arr2 2中删除@arr2 1的第一个匹配元素,即在上面的示例中,我需要从@arr2 2中移除原元素。

目前,我的逻辑如下。

代码语言:javascript
复制
#!/usr/bin/perl
my @arr1 = qw( jon won don pon );
my @arr2 = qw( son kon bon won kon don pon won pon don won);
my @remove_indices = ();
my $remove_element;
my $first_remove_index;
OUTER_FOR: for my $i (0..@arr2) {
    $outer_element = $arr2[$i];
    foreach my $innr_element ( @arr1 ) {
        if($innr_element eq $outer_element) {
            push(@remove_indices, $i);
            $first_remove_index = $i;
            $remove_element = $innr_element;
            last OUTER_FOR;
        }
    }
}

for my $i ($first_remove_index+1..@arr2) {
    $outer_element = $arr2[$i];
    if($remove_element eq $outer_element) {
        push(@remove_indices, $i);
    }
}

if (@remove_indices > 0) {
        map {splice (@arr2, $_, 1)} reverse(@remove_indices);
                                    }

print "@arr2";

但它似乎是典型的C/C++风格的逻辑。我不能用哈希。有什么perl方法可以这样做吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-09-02 09:07:47

下面是另一种方法(假设您希望删除第一个匹配元素的所有出现):

代码语言:javascript
复制
use strict;
use warnings;

my @arr1 = qw(jon won don pon);
my @arr2 = qw(son kon bon won kon don pon won pon don won);

for my $elem (@arr2){
    if(grep { $_ eq $elem } @arr1){
        @arr2 = grep { $_ ne $elem } @arr2;
        last;
    }
}

print "@arr2";

输出:

代码语言:javascript
复制
son kon bon kon don pon pon don
票数 1
EN

Stack Overflow用户

发布于 2013-09-02 18:02:26

病毒,当然您可以使用散列来解决这个问题。

实际上,如果在示例中扩展一个或两个数组的大小,那么它将提供更好的CPU使用量。

代码语言:javascript
复制
use strict;

my @arr1 = qw(jon won don pon);
my @arr2 = qw(son kon bon won kon don pon won pon don won);

my $i;
my %h;
for (@arr2) { push @{$h{$_} }, $i++ }
for my $a (@arr1) {
    if (exists $h{$a}) {
        for (@{$h{$a}}) {
            $arr2[$_] = '';
        }
        last;
    }
}

@arr2 = grep { length } @arr2;
print "@arr2\n";

我对不同的解决方案的相对效率感到好奇,并编写了一个测试程序来测试它们。当你使用你的测试数据时,你会很高兴地知道你的程序是好的。但是当数组的大小开始增长时,就不会了!

下面的内容有点疯狂,我知道,但不管怎样。但是,如果您每天要运行您的应用程序数以百万计的次数,那么您可能会受益于对您的硬件进行一些基准测试。所以请容忍我:)

以下是5个解决方案的相对CPU时间,按上面发布的顺序排列(最经济的是显示为"1")。第一个结果列使用在您的示例中使用的数据保存CPU时间,下面三个列增加了两个数组中的一个或两个数组,其前缀为50个元素,这些元素的内容在另一个数组中找不到。

代码语言:javascript
复制
First array                @arr1     @arr1   @arr1+50  @arr1+50
Second array               @arr2   @arr2+50    @arr2   @arr2+50

Your program                 1         7         3        45
Grep approach 1              1         6         3        43
Grep approach 2              3         9        33       160
Convert to string            2         4         3         6
Using hash                   2         6         2         7

当在测试数据上运行时,哈希解决方案的CPU密集型是您的两倍。但是,如果将第二个数组扩展50个元素,则哈希会稍微好一些,因为您的CPU时间现在已经增加到7个,而哈希方法已经从2个增加到6个。但是如果这两个数组都更大,那么程序需要的CPU是原始数据的45倍,而哈希程序只需要3.5倍(从2到7)。

显然,随着数组大小的增长,它们都需要更多的CPU时间,但不是以相同的比例增长,而且它们的减速也不是线性的。它们可能也会被稍微调整一下,我想结果会在不同的硬件平台上发生变化,但这些应该可以合理地表明它们的相对效率。下面是原始数组由100个元素而不是50个元素生成的时间。

代码语言:javascript
复制
First array                @arr1     @arr1  @arr1+100  @arr1+100
Second array               @arr2  @arr2+100    @arr2   @arr2+100

Your program                 1        12         5       173
Grep approach 1              1        12         4       162
Grep approach 2              3        16        68       612
Convert to string            2         7         5        12
Using hash                   2        11         3        12

因此,对于是否应该采用第四种方法(将测试数组转换为单个字符串,然后通过regex,一个死掉的perl程序员的解决方案)和第五种方法(使用哈希),这是一种猜测。稍微地说,“转换为字符串”的方法更好,这对许多程序员来说是违反直觉的。它也很短,也很容易阅读。

底线是..。如果您使用的数据集类似于示例中的数据集,那么您的代码很好(尽管您应该在INNER_LOOP: to read“(0..$#arr2)”中修复“(0.@arr2 2)”)。

否则,使用第4或第5取决于你的口味。我个人会选择一个不是我的,“转换到字符串”程序,只要我100%确定加入字符不会出现在数据中。

我想我最好现在回去做一些有成效的事情:)

票数 1
EN

Stack Overflow用户

发布于 2013-09-02 08:51:20

您可以使用一个简单的for循环,并在找到匹配时使用last退出循环。使用grep删除关键字。

代码语言:javascript
复制
use strict;
use warnings;

my @arr1 = qw( jon won don pon );
my @arr2 = qw( son kon bon won kon don pon won pon don won);
my @out;
for my $word (@arr1) {
    my @new = grep !/^\Q$word\E$/, @arr2;
    if (@new != @arr2) {
        print "'$word' found\n";
        @out = @new;
        last;
    }
}
print "@out";

请注意,我使用\Q ...\E禁用可能的regex元字符。!=比较将比较数组大小,当发现差异时,我们知道我们找到了匹配的数组。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18568467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档