2013-09-27 24 views
2

鉴于此字符串:枚举下令所有可能的长度标记在Perl

<VACC-PROP-0><VACC-PROP-0><NUM><EXP-V-0><MIR-0><PREP> 

我想要做的是枚举所有可能的有序长度是这样的:

<VACC-PROP-0><VACC-PROP-0><NUM><EXP-V-0><MIR-0><PREP> 
<VACC-PROP-0><VACC-PROP-0><NUM><EXP-V-0><MIR-0> 
<VACC-PROP-0><VACC-PROP-0><NUM><EXP-V-0> 
<VACC-PROP-0><VACC-PROP-0><NUM> 
<VACC-PROP-0><VACC-PROP-0> 
<VACC-PROP-0> 

<VACC-PROP-0><NUM><EXP-V-0><MIR-0><PREP> 
<NUM><EXP-V-0><MIR-0><PREP> 
<EXP-V-0><MIR-0><PREP> 
<MIR-0><PREP> 
<PREP> 

不是说上面是手工完成。我可能会错过一些东西。 但这个想法是确定所有长度(令牌的数量)的所有可能的有序令牌。 我试过这段代码但失败了,最好的办法是什么?

use Data::Dumper; 
my $str = "<VACC-PROP-0><VACC-PROP-0><NUM><EXP-V-0><MIR-0><PREP>"; 

# Remove all the brackets 
my @tokens = grep {!/^$/} split(/[><]/,$str); 

# Print the combinations 
foreach my $i (0 .. $#tokens) { 

    print join(" ", @tokens[0..$i]),"\n"; 
} 

执行此:https://eval.in/51023

回答

4

你想任意深度的嵌套循环。

for my $use_token0 (0..1) { 
    for my $use_token1 (0..1) { 
     for my $use_token2 (0..1) { 
     ... 
     } 
    } 
} 

对于这一点,你用Algorithm::LoopsNestedLoops

use Algorithm::Loops qw(NestedLoops); 

my $str = "<VACC-PROP-0><VACC-PROP-0><NUM><EXP-V-0><MIR-0><PREP>"; 
my @tokens = split /(?<=>)(?=<)/, $str; 

my $iter = NestedLoops([ ([0,1]) x @tokens ]); 
while (my @bools = $iter->()) { 
    say @tokens[ grep $bools[$_], 0..$#tokens ]; 
} 

虽然,在这种情况下,你可以简单地使用

my $str = "<VACC-PROP-0><VACC-PROP-0><NUM><EXP-V-0><MIR-0><PREP>"; 
my @tokens = split /(?<=>)(?=<)/, $str; 

for my $i (0 .. (1<<@tokens)-1) { 
    say @tokens[ grep $i & (1 << ($#tokens-$_)), 0..$#tokens ]; 
} 
+0

始终是个天才,我从下午就知道了。顺便说一句,给定一个像1234(每个数字代表一个标记)的字符串,有没有一种方法来按顺序枚举,但允许在它们之间丢失标记。例如1234,123,12,13,14,23,24,34,234等。 – neversaint

+1

我没有在那里看到订单 – ikegami

+0

13是按原始字符串排列但不是31. – neversaint