web-dev-qa-db-ja.com

数値を数値に、文字列をアルファベット順に並べ替える

それは非常に簡単な問題ですが、それを回避することができません。ハッシュの配列があります。次のようなデータ構造:

my @unsorted = (
    {
        'key_5' => '14.271 text',
        # ...
    },
    {
        'key_5' => 'text',
        # ...
    },
    {
        'key_5' => '13.271 text',
        # ...
    },
    {
        'key_5' => 'etext',
        # ...
    },
);

ハッシュのkey_5に基づいて配列を並べ替える方法を教えてください。文字列部分はアルファベット順にソートする必要があります。キーがnumber stringの場合(形式は常にこのようになります)、数値で(文字列部分を完全に無視して)ソートする必要があります。したがって、出力は次のいずれかになります。

my @sorted = (
    {
        'key_5' => 'etext',
        # ...
    },
    {
        'key_5' => 'text',
        # ...
    },
    {
        'key_5' => '13.271 text',
        # ...
    },
    {
        'key_5' => '14.271 text',
        # ...
    },
);

したがって、配列要素はハッシュ要素のkey_5に基づいてソートされます。

重要:ネイティブPerlインストールに同梱されていないPerlパッケージは使用できません。Perl5.18を使用しています

3
tt_pre

Sort :: Key :: Natural の使用:

use Sort::Key::Natural qw( natkeysort );

my @sorted = natkeysort { $_->{key_5} } @unsorted;

上記はあなたの入力から以下を生成します:

[
    {
        'key_5' => '13.271 text'
        # ...
    },
    {
        'key_5' => '14.271 text'
        # ...
    },
    {
        'key_5' => 'etext'
        # ...
    },
    {
        'key_5' => 'text'
        # ...
    },
]

それでも不十分な場合は、以下を使用できます。

use Sort::Key::Multi qw( unskeysort );   # uns = (u)nsigned int, (n)umber, (s)tring

my @sorted =
   unskeysort {
      $_->{key_5} =~ /^([0-9.]+)\s+(.*)/s
         ? ( 1, $1, $2 )
         : ( 0, 0, $_->{key_5} )
   }
      @unsorted;
2
ikegami