2011-02-09 54 views
1

目前,我使用以下代碼將不規則多維數組轉換爲一維數組。將多維數組轉換爲一維數組的更好方法

my $array = [0, 
     [1], 
     2, 
     [3, 4, 5], 
     [6, 
      [7, 8, 9 ], 
     ], 
     [10], 
     11, 
     ]; 

my @mylist; 
getList($array); 

print Dumper (\@mylist); 


sub getList 

{ 

     my $array = shift; 

     return if (!defined $array); 
     if (ref $array eq "ARRAY") 
     { 
       foreach my $i (@$array) 
       { 
        getList($i); 
       } 
     } 
     else 
     { 
       print "pushing $array\n"; 
       push (@mylist, $array); 
     } 
} 

這是基於遞歸的,我在檢查每個元素。如果元素是對數組的引用,則使用新數組遞歸地調用它。

有沒有更好的方法來解決這類問題?

回答

7

首先不應該通過修改一個全局變量返回的數據。改爲返回列表。

至於效率,Perl有一個驚人的大函數調用開銷。因此,對於大數據結構,我寧願採用非遞歸方法。像這樣:

use Data::Dumper; 
my $array = [ 
    0, 
    [1], 
    2, 
    [3, 4, 5], 
    [6, [7, 8, 9 ]], 
    [10], 
    11, 
]; 

my @mylist = get_list($array); 

print Dumper (\@mylist); 

sub get_list { 
    my @work = @_; 
    my @result; 
    while (@work) { 
     my $next = shift @work; 
     if (ref($next) eq 'ARRAY') { 
      unshift @work, @$next; 
     } 
     else { 
      push @result, $next; 
     } 
    } 
    return @result; 
} 

請注意,我在此處使用的格式與perlstyle的建議相匹配。我們都知道爭論One True Brace Style的徒勞無益。但至少我會建議你減少8個空格縮進。對此進行了研究,並且在2-4個空間範圍內縮進代碼的理解已被證明有所改進。詳情請閱讀Code Complete。對於年輕人來說,這個範圍在哪裏並不重要,但年齡較大的程序員的視力會更好。有關更多信息,請閱讀Perl Best Practices

+0

應該添加「使用Data :: Dumper qw(Dumper);」代碼示例。 – 2011-02-09 13:30:28

0

在一般情況下,這是做到這一點的唯一方法。

當您遇到ArrayRef時,您只需再次調用getList()就可以優化您的代碼。如果您發現常規值,則可以直接將其推入@mylist而不是重新運行getList()。

0

我已經使用過這個了。此代碼是在命令行上,但你可以把單引號中的代碼到你的特等文件中所有的功能

$ perl -le' 
use Data::Dumper; 
my @array = (1, 2, 3, [ 4, 5, 6, [ 7, 8, 9 ] ], [ 10, 11, 12, [ 13, 14, 15 ] ], 16, 17, 18); 
sub flatten { map ref eq q[ARRAY] ? flatten(@$_) : $_, @_ } 
my @flat = flatten @array; 
print Dumper \@flat; 
' 
+2

不,perl沒有扁平的方法。你的代碼定義了一個扁平化方法,並在數組上進行遞歸。 – ghandi 2011-02-09 13:09:05

2

通常用迭代代替遞歸通常會更好。對於一般的技術,看到在這種情況下,高階的Perl書(自由avaialble)第5章:

my @stack = ($array); 
my @flattened; 
while (@stack) { 
    my $first = shift @stack; 
    if (ref($first) eq ref([])) { 
     push @stack, @$first; # Use unshift to keep the "order" 
    } else { 
     push @flattened, $first; 
    } 
} 

它的更好的原因是遞歸的實現:

  • 風險運行到堆棧溢出,如果有太多的嵌套級別

  • 效率較低,由於遞歸調用的成本

3

使用CPAN。直到你知道這是一個問題,不要擔心遞歸開銷。

#!/usr/bin/perl 
use strict; 
use warnings; 
use List::Flatten::Recursive; 

my $array = [ 
    0, 
    [1], 
    2, 
    [3, 4, 5], 
    [6, [7, 8, 9 ]], 
    [10], 
    11, 
]; 

my @result = flat($array); 
print join(", ", @result), "\n";