2014-12-22 50 views
1

如果我有一個像下面這樣的數組,其中元素的順序是隨機的,並且每個元素可以具有多少個級別沒有限制。這裏只顯示3個關卡。 abc如何正則表達式匹配a/b/c ...?

我希望能夠解析這樣的陣列,並將結果存儲在哈希像這樣的哈希,當只有3個級別

$VAR1 = { 
      'a' => { 
        'b' => 'c' 
       } 
     }; 

問題

我的問題是如何爲此寫一個正則表達式,因爲第一級最後沒有/,並且由於元素的順序是隨機的,如果a/b/c已經插入到散列中,那麼元素a不應該刪除密鑰的散列值。

如何解決這樣的問題?

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 

my @ar = ("a", "a/b", "a/b/c"); 
my %h =(); 

foreach my $a (@ar) { 
} 
+5

不要使用正則表達式。 –

+1

如何處理''a「'輸入?在這種情況下,值應該是什麼並不明顯,並且散列不能只有一個鍵。 –

+1

如果這是您正在嘗試解析的路徑,請改爲使用「File :: Spec」模塊splitdir。 – TLP

回答

2
#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 
use Data::Diver 'DiveRef'; 

my @array = ("a", "a/b", "a/b/c"); 
my %hash =(); 

foreach my $element (@array) { 
    DiveRef(\%hash, \(split /\//, $element)); 
} 

通常你會分配給或修改DiveRef返回的標量引用(或指定DiveVal的結果),但在這裏你只是想確定密鑰存在。

\(...)將拆分返回的列表轉換爲標量引用列表,這告訴Data :: Diver它們總是要作爲散列鍵,如果它們是數字,則不可能是數組索引。

0

一個例子:

my @ar = ("a", "a/b", "a/b/c"); 
my %h; 

for (@ar) { 
    my $levels = split /\//; 

    for (my $i = 0; $i <= $#levels; $i++) { 
     # How ever you want to set-up your hash of hashes 
     # But each for loop iteration would give you a "level" of input 
    } 
} 
2

要獲得

"a"     => $tree = "a"; 
"a", "a/b"   => $tree = { "a" => "b" }; 
"a", "a/b", "a/b/c" => $tree = { "a" => { "b" => "c" } }; 
"a", "a/b", "a/c" => $tree = { "a" => { "b" => undef, "c" => undef } }; 

代碼:

my $tree; 
for ("a", "a/b", "a/b/c") { 
    my @keys = split qr{/}; 
    my $val = pop(@keys); 

    my $p = \$tree; 
    while (@keys) { 
     my $key = shift(@keys); 
     $$p = { $$p => undef } if !ref($$p); 
     $p = \(($$p)->{$key}); 
    } 

    if (defined($$p)) { 
     $$p = { $$p => undef } if !ref($$p); 
     ($$p)->{$val} = undef; 
    } else { 
     $$p = $val; 
    } 
} 

但既然你需要使用ref瀏覽它,這不是一個很好的數據結構。相反,我建議

"a"     => $tree = { "a" => undef }; 
"a", "a/b"   => $tree = { "a" => { "b" => undef } }; 
"a", "a/b", "a/b/c" => $tree = { "a" => { "b" => { "c" => undef } } }; 
"a", "a/b", "a/c" => $tree = { "a" => { "b" => undef, "c" => undef } }; 

代碼:

my $tree; 
for ("a", "a/b", "a/b/c") { 
    my $p = \$tree; 
    $p = \(($$p)->{$_}) for split qr{/}; 
} 

看到它是多麼簡單建立這個數據結構?當您嘗試導航時,您會獲得類似的好處。


請注意,您可以使用Data::Diver創建第二個數據結構(雖然我記得它是慢得多)。

use Data::Diver qw(DiveRef); 

my $tree; 
for ("a", "a/b", "a/b/c") { 
    DiveRef($tree //= {}, \split(qr{/})); 
}