在Perl中枚举具有所有可能长度的有序标记

时间:2013-09-27 03:09:16

标签: perl token

鉴于此字符串:

<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

1 个答案:

答案 0 :(得分: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 ];
}