了解元素的顺序

时间:2018-05-10 18:34:55

标签: perl sorting machine-learning

我想找到一种有效的方法(最好是在Perl中),通过比较它们在组的多个子集中的顺序来学习单词族的固定顺序。 (它们是工作参数。大约有30种不同的工作参数。不同的工作需要不同的参数组合,而且每项工作中只有一些参数)

例如,给定:

first
second
third
sixth
seventh
tenth

first
third
fourth
fifth
sixth

third
fifth
seventh
eighth
ninth
tenth

它应该能够记住它看到的相对顺序关系,以确定订单是:

first
second
third
fourth
fifth
sixth
seventh
eighth
ninth
tenth

我已生成如下列表:

first.second.third.sixth.seventh.tenth
first.third.fourth.fifth.sixth
third.fifth.seventh.eighth.ninth.tenth

然后按字母顺序进行排序,并在视觉上对它们进行比较,但我有30个参数的数百种不同组合,因此将它们全部排序并手动将它们放在一起将是一项很大的工作。

我认为@ daniel-tran已经回答了"怎么"在https://stackoverflow.com/a/48041943/224625并使用它和一些hackery,如:

$order->{$prev}->{$this} = 1;
$order->{$this}->{$prev} = 0;

我设法为每对连续参数填充一个哈希值为1或0的哈希值,说明哪个是第一个,如:

$VAR1 = {
    'first' => {
        'second' => 1,
        'third' => 1,
    },
    'second' => {
        'first' => 0,
        'third' => 1,
    },
    'third' => {
        'first' => 0,
        'second' => 0,
        'fourth' => 1,
        'fifth'  => 1,
        'sixth'  => 1,
    },            
    'fourth' => {
        'third' => 0,
        'fifth' => 1,
    },
    ...

但当我要求对一对从未被视为直接邻居的人进行排序时,我试图找出在我的排序功能中应该做些什么,因此没有定义关系。

有一个简单的解决方案吗? 我是以正确的方式来做这件事的吗? 首先是否有更好的WTDI?

谢谢,

约翰

2 个答案:

答案 0 :(得分:8)

使用图表和拓扑排序链接到includes another answer的问题。 Graph模块非常易于使用:

use warnings;
use strict;
use Graph;

my $graph = Graph->new(directed => 1);
my $prev;
while (<DATA>) {
    chomp;
    $graph->add_edge($prev, $_) if length && length $prev;
    $prev = $_;
}
print $_,"\n" for $graph->topological_sort;

__DATA__
first
second
third
sixth
seventh
tenth

first
third
fourth
fifth
sixth

third
fifth
seventh
eighth
ninth
tenth

输出:

first
second
third
fourth
fifth
sixth
seventh
eighth
ninth
tenth

答案 1 :(得分:3)

我试图自己实施一个天真的解决方案。我构建了%order哈希值,其中每个键的值都是跟随它的元素。然后我创建了这个结构的传递闭包(即如果firstsecond之前,而secondthird之前,那么first必须在{{1}之前}})。如果有足够的信息,每个键将具有不同数量的值,并且按值的数量对元素进行排序将给出有序列表。

third

输出

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my @partial = (
    [qw[ first second third sixth seventh tenth ]],
    [qw[ first third fourth fifth sixth ]],
    [qw[ third fifth seventh eighth ninth tenth ]]);

my %order;
my %all;
for my $list (@partial) {
    undef @all{ @$list };
    undef $order{ $list->[ $_ - 1 ] }{ $list->[$_] }
        for 1 .. $#$list;
}

my $changed = 1;
while ($changed) {
    undef $changed;
    for my $from (keys %order) {
        if (my @to = keys %{ $order{$from} }) {
            if (my @to2 = map keys %{ $order{$_} }, @to) {
                my $before = keys %{ $order{$from} };
                undef @{ $order{$from} }{@to2};
                $changed = 1 if $before != keys %{ $order{$from} };
            }
        }
    }
}

my %key_counts;
$key_counts{ keys %{ $order{$_} } }++ for keys %order;
warn "Not enough information\n"
    if keys %key_counts != keys %order;

say join ' ',
    sort { keys %{ $order{$b} } <=> keys %{ $order{$a} } }
    keys %order;