1

假设我有一个包含单词的列表和另一个包含与这些单词相关的置信度的列表:

my @list = ("word1", "word2", "word3", "word4");
my @confidences = (0.1, 0.9, 0.3, 0.6);

我想获得第二对列表,其元素的@list置信度高于0.4排序顺序,以及它们相应的置信度。我如何在 Perl 中做到这一点?(即使用用于排序另一个列表的索引列表)

在上面的示例中,输出将是:

my @sorted_and_thresholded_list = ("word2", "word4");
my @sorted_and_thresholded_confidences = (0.9, 0.6);
  • @list 中的条目可能不是唯一的(即排序应该是稳定的)
  • 排序应按降序排列。
4

5 回答 5

5

在处理并行数组时,必须使用索引。

my @sorted_and_thresholded_indexes =
    sort { $confidences[$b] <=> $confidences[$a] }
     grep $confidences[$_] > 0.4,
      0..$#confidences;

my @sorted_and_thresholded_list =
   @list[ @sorted_and_thresholded_indexes ];
my @sorted_and_thresholded_confidences =
   @confidences[ @sorted_and_thresholded_indexes ];
于 2012-09-14T15:28:29.003 回答
3

使用List ::MoreUtils和:pairwisepart

use List::MoreUtils qw(pairwise part);
my @list = ("word1", "word2", "word3", "word4");
my @confidences = (0.1, 0.9, 0.3, 0.6);

my $i = 0;
my @ret = part { $i++ % 2 } 
          grep { defined } 
          pairwise { $b > .4 ? ($a, $b) : undef } @list, @confidences;

print Dumper @ret;

输出:

$VAR1 = [
          'word2',
          'word4'
        ];
$VAR2 = [
          '0.9',
          '0.6'
        ];
于 2012-09-14T15:29:52.213 回答
1

如果您确定不会有重复的单词,我认为在此任务中使用哈希可能更容易,例如:

my %hash = ( "word1" => 0.1,
             "word2" => 0.9,
             "word3" => 0.3,
             "word4" => 0.6
           );

然后您可以遍历哈希中的键,只找出符合您的条件的键:

foreach my $key (keys %hash) {
    if ($hash{$key} > 0.4) {
        print $key;
    }
}
于 2012-09-14T15:26:00.533 回答
1

尽管ikegami已经说明了我的首选解决方案 - 使用索引 - 还有将数组组合成二维数组 (*) 的选项。好处是数据都被收集到同一个数据结构中,因此很容易操作。

use strict;
use warnings;
use Data::Dumper;

my @list = ("word1", "word2", "word3", "word4");
my @conf = (0.1, 0.9, 0.3, 0.6);
my @comb;

for (0 .. $#list) {                       # create two-dimensional array
    push @comb, [ $list[$_], $conf[$_] ];
}

my @all = sort { $b->[1] <=> $a->[1] }    # sort according to conf
          grep { $_->[1] > 0.4 } @comb;   # conf limit

my @list_done = map $_->[0], @all;        # break the lists apart again
my @conf_done = map $_->[1], @all;

print Dumper \@all, \@list_done, \@conf_done;

输出:

$VAR1 = [
          [
            'word2',
            '0.9'
          ],
          [
            'word4',
            '0.6'
          ]
        ];
$VAR2 = [
          'word2',
          'word4'
        ];
$VAR3 = [
          '0.9',
          '0.6'
        ];

(*) = 使用哈希也是一种选择,假设 1) 原始顺序不重要,2) 所有单词都是唯一的。但是,除非快速查找是一个问题,否则使用数组没有缺点。

于 2012-09-14T16:38:32.107 回答
1
my @list = ("word1", "word2", "word3", "word4");
my @confidences = (0.1, 0.9, 0.3, 0.6);

my @result = map { $list[$_] }
              sort { $confidences[$b] <=> $confidences[$a] }
                 grep { $confidences[$_] > 0.4 } (0..$#confidences);
于 2012-09-15T00:20:11.463 回答