2

別のリストで定義された順序で、ハッシュから値を取得する方法を探しています。

「デモ」コード(実際の値は異なります):

use 5.014;
use warnings;

my $href = {
    'Long one' => 'v1',
    'xxx two'  => 'v2',
    'another3' => 'v3',
    'xfour'    => 'v4',
    'some5'    => undef,
};

#keys from the $href in defined order
my @order = ('Long one', 'xfour', 'nono', 'another3', 'some5', 'xxx two');

#in the real code:
#my $href = some_sub(......);  my @order = another_sub(....);

#cleanup the @order form undefined values
@order = grep { exists $href->{$_} && defined $href->{$_} } @order;

#my input
while(<DATA>) {
    chomp;

    #filter out nonexistent keys and undefined values
    my @defined_data = grep { exists $href->{$_} && defined $href->{$_} } split '/';

    my $str = "xx";
    $str = join('/',
               map { $href->{$_} }  some_my_sort(@defined_data)
    ) if @defined_data;

    say $str;
}

sub some_my_sort {
    my(@list) = @_;

    # "somewhat"sort the @list in order defined by @order
    # haven't any idea how to do this :(

    # __HERE NEED HELP__ to sort the @list, to the order defined in the @order

    #and get only first two values. if exists only one value, return only one
    if($#list > 0) {
        return ($list[0], $list[1]);
    }
    else {
        return($list[0]);
    }
}

__DATA__
another3/some5/Long one/xfour/xxx two
xxx two/blabla/some5/another3/xfour
some5
notexists/some5/xxx two/Long one
some5/another3

上記の入力の場合、次の出力を取得します。

v1/v4
v4/v3
xx
v1/v2
v3

@ikegamiソリューションを形成する:

use 5.014;
use warnings;

my $href = { 'Long one' => 'v1', 'xxx two'  => 'v2', 'another3' => 'v3', 'xfour'    => 'v4', 'some5'    => undef, };
my @order = ('Long one', 'xfour', 'nono', 'another3', 'some5', 'xxx two');
@order = grep { exists $href->{$_} && defined $href->{$_} } @order;

my %order = map { $order{$_} => $_ } 0..$#order;
while (<DATA>) {
    chomp;
    my @keys = grep { defined $href->{$_} } split '/';
    @keys = sort { $order{$a} <=> $order{$b} } @keys;
    splice(@keys, 2) if @keys > 2;
    @keys = 'xx' if !@keys;
    say join '/', @{$href}{ @keys };
}

次の-エラー-を取得し、その理由を本当に理解していません:

Global symbol "%order" requires explicit package name at ike line 8.
Execution of ike aborted due to compilation errors.
4

1 に答える 1

7

@orderを定義した後、%order_hを定義します。

my %order_h;
my $i = 0;
$order_h{$_} = $i++ for @order;

次に、並べ替えに関するコメントの代わりに、次の行を追加します。

@list = sort { $order_h{$a} <=> $order_h{$b} } @list;

コード全体のクリーンアップバージョンは次のとおりです。

my %order = map { $order[$_] => $_ } 0..$#order;

while (<DATA>) {
    chomp;
    my @keys = grep { defined $href->{$_} } split '/';
    @keys = sort { $order{$a} <=> $order{$b} } @keys;
    splice(@keys, 2) if @keys > 2;
    say join '/', @keys ? @{$href}{ @keys } : 'xx';
}
于 2012-09-14T15:05:10.373 に答える