移除冗余的数组元素

4
我有一个包含许多主机名的数组。我想要删除此数组中的冗余元素,即:
  • 如果存在重复条目,则删除其中一个。
  • 如果同时存在www.example.comexample.com,则删除www.example.com
删除重复项已经在这里得到解答,但是如何实现第二个条件呢?
编辑:为了澄清,我必须提到www.可能不是唯一存在的内容--它也可以是abc.def.ghi.foo.bar.baz.quxfoo.bar.baz.qux,在这种情况下,前者将被删除。
2个回答

3

你的意思是要删除已经存在后缀的元素。我们可以将后缀问题转化为前缀问题。因为在有序数组中,前缀会在字符串本身之前出现。所以,如果前一个字符串是目标字符串的前缀,那么我们就可以删除它。

my @array = qw(foo.com bar.net www.example.com example.com
            abc.def.ghi.foo.bar.baz.qux foo.bar.baz.qux);
my @result = do {
    my $p;
    map scalar reverse, grep {
        my $x = !defined $p || !m/^\Q$p/;
        if($x) {
            $p = $_;
            $p .= '.' unless m/\.$/;
        }
        $x
    } sort map scalar reverse, @array;
};

use 5.10.0;
say for @result;

1
非常聪明的解决方案。只是忽略了一个特殊情况,即一个条目是另一个条目的子字符串,但它们实际上并不相关。例如,foo.com和barfoo.com。通过添加以下代码轻松解决:$p = $_ if $x; $p .= '.' if $p !~ /\.$/; - Miller

0

这里开始,在主要的foreach中,我们将通用的已经查看的条目映射到%seen哈希表中。

#1处有一个技巧:我们知道$k是一个主机名,因此我们检查它是否以www.字符串开头,更好的做法是:每个键(我的意思是每个$k)都被强制以www.开头。

#2附近,您可以使用其他正则表达式来细化$k值(修剪空格,删除结尾斜杠或http://等)

#!/usr/bin/perl -w

use warnings;
use strict;

my @hostnames = qw(foo.com bar.net www.example.com example.com);
my %seen = ();
my @result = ();

foreach my $k (@hostnames) {
    $k = "www." . $k if not $k =~ /^www\./; #1
    ... #2
    if (not $seen{$k}) {
        push @result, $k;
        $seen{$k} = 1;
    }
}

结果是一个具有唯一 www. 开头主机名的数组:

www.foo.com
www.bar.net
www.example.com

请看一下澄清后的问题,谢谢。(它可能不仅限于www.,可能是任何东西。) - user2064000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接