2014-02-25 115 views
4

我有一个包含许多主机名的数组。我想删除该阵列的冗余元素,即:删除冗余阵列元素

  • 如果存在重复条目,则删除其中的一个。
  • 如果www.example.comexample.com都存在,则删除www.example.com

删除重复已经回答here,但我怎么acheive第二个条件?

编辑:为了澄清,我必须提到,www.可能不存在的唯一的东西 - 它很可能会成为abc.def.ghi.foo.bar.baz.quxfoo.bar.baz.qux,在这种情况下,前者被删除。从here

回答

4

所以你说你想删除后缀已经存在的元素。那么我们可以将后缀问题转换为前缀问题。然后,我们可以使用有序数组前缀中的特征在字符串本身之前。然后我们删除字符串,如果前面的字符串是其前缀

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。='。'如果$ p!〜/\.$/;' – Miller

0

开始,在主foreach我们映射,到%seen哈希,通用已经看到条目

#1说到诀窍:我们知道,$k是hostaname,所以我们检查它是否与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 
+0

请看看澄清的问题,谢谢。 (它可能不限于'www.',可能是任何东西。) – user2064000