2

给定这个字符串:

<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

1 回答 1

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 ];
}
于 2013-09-27T03:22:30.117 回答