2

次のような 1,660 行の配列があります。

...
H00504
H00085
H00181
H00500
H00103
H00007
H00890
H08793
H94316
H00217
...

そして主人公は変わらない。常に「H」の場合は 5 桁です。しかし、Perl での数値ソートであると信じていることを実行すると、奇妙な結果が得られます。一部のセグメントは順番にソートされますが、別のセグメントが開始されます。ソート後のセグメントは次のとおりです。

...
H01578
H01579
H01580
H01581
H01582
H01583
H01584
H00536
H00537
H00538
H01585
H01586
H01587
H01588
H01589
H01590
...

私がしようとしているのはこれです:

my @sorted_array = sort {$a <=> $b} @raw_array;

しかし、明らかにそれは機能していません。理由を知っている人はいますか?

これらの値はすべて先頭に「H」が付加されていますが、将来、他の文字が先頭に付加された追加データになる可能性があることを付け加えておきます。これは、H を削除し、並べ替えてから H を置き換えることは解決策ではないことを意味します。

4

5 に答える 5

9

本来の方法で使用use strict; use warnings;していた場合、フォームのエラーが多数発生していたはずです

Argument "H01578" isn't numeric in numeric comparison (<=>)

どの要素も数値ではないため、すべてゼロと見なされます。これが、Perl が現在のコードの結果をソート済みと見なす理由です。


文字で並べ替えてから数字で並べ替える場合 (すべての文字が同じであるため、数字だけで並べ替えるのと同じです):

my @sorted_array = sort @raw_array;

の略です

my @sorted_array = sort { $a cmp $b } @raw_array;

先頭の文字に関係なく数字で並べ替えたい場合は、代わりに次を使用します。

my @sorted_array =
   sort { substr($a, 1) <=> substr($b, 1) }
    @raw_array;
于 2012-10-12T02:19:32.397 に答える
5

最初の文字を主キーとして並べ替え、次に数字を二次キーとして並べ替える場合は、並べ替えの前にすべてのデータから比較のために 2 つのフィールドを抽出するシュワルツ変換のバリエーションを使用できます。

このプログラムは

use strict;
use warnings;

my @data = <DATA>;
chomp @data;

my @sorted = sort map $_->[0],
sort { $a->[1] cmp $b->[1] or $a->[2] <=> $b->[2] }
map [$_, /(.)(.+)/], @data;

print "$_\n" for @sorted;

__DATA__
A1180
B0802
B1284
C0899
C1455
C0765
A1207
A0909
C0921
C1060
A1067
B1486
A1268
B0772
C0595
B0734
A1004
A0607
A1323
B1181

出力

A0607
A0909
A1004
A1067
A1180
A1207
A1268
A1323
B0734
B0772
B0802
B1181
B1284
B1486
C0595
C0765
C0899
C0921
C1060
C1455

ツールが正常に完了しました

Transform を使用しない別の方法を好むかもしれません。このプログラムの出力は同じですが、大規模なデータセットでは実行速度が大幅に遅くなります

my @sorted = sort {
  my @a = $a =~ /(.)(.+)/;
  my @b = $b =~ /(.)(.+)/;
  $a[0] cmp $b[0] or $a[1] <=> $b[1];
} @data;
于 2012-10-12T07:46:57.713 に答える
1

次のようなものが必要です。

my @sorted_array = sort {substr($a, 1) <=> substr($b,1)} @raw_array;

例については、http: //ideone.com/trnfyを参照してください。

なしで標準の並べ替えを使用した場合{...}も同様に機能するはずです。英数字データの数値比較を行っているため、すべての比較が 0 を返すため、現在のコードはおそらく失敗しています。

于 2012-10-12T02:03:06.667 に答える
1

以下を使用して、シュワルツ変換およびその他の関連するノイズを回避できますList::UtilsBy::sort_by

use List::UtilsBy qw( sort_by );

my @sorted_array = sort_by { substr($_, 1) } @raw_array;
于 2012-10-12T13:43:32.760 に答える