複数の列を並べ替えようとしています。結果は予想と異なっていた。
これは私のデータです(people.txt)。
Simon Strange 62
Pete Brown 37
Mark Brown 46
Stefan Heinz 52
Tony Bedford 50
John Strange 51
Fred Bloggs 22
James Bedford 21
Emily Bedford 18
Ana Villamor 44
Alice Villamor 50
Francis Chepstow 56
以下は正しく実行されます。
bash-3.2$ sort -k2 -k3 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
しかし、以下は期待どおりに機能しません。
bash-3.2$ sort -k2 -k1 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
姓、名前の順に並べ替えてみましたが、Veramosの順序が正しくないことがわかります。姓でソートしてから姓が一致したら、名前でソートしたいです。
私はこれがどのように機能するのか理解できないようです。もちろん、他の方法(awkを使用して)を実行することもできますが、ソートを理解したいと思います。
私はMac OS Xで標準のBashシェルを使用しています。
答え1
キーなどの指定は、-k2
2から行末までのすべてのフィールドが考慮されることを意味します。だからVillamor 44
それは前に終わったVillamor 50
。 2つの行は同じではないので、最初の比較sort -k2 -k1
だけで2つの行を区別するのに十分であり、2番目の-k1
ソートキーは呼び出されません。 2人のVillamoが同じ年齢の場合は、名前に基づいて-k1
ソートされます。
単一列でソートするには、-k2,2
キー仕様として使用してください。これは、#2から#2までのフィールド、つまり2番目のフィールドのみを使用することを意味します。
sort -k2 -k3 <people.txt
重複:sort -k2 <people.txt
姓、名、年齢に基づいてソートするには、次のコマンドを実行します。
sort -k2,2 -k1,1 <people.txt
または、同様に、sort -k2,2 -k1 <people.txt
これら3つのフィールドのみがあり、区切り文字が同じであるためです。実際、行サブセットのすべてのキーが同じ場合、最後の手段として行全体を使用するのとsort -k2,2 <people.txt
同じ効果が得られます。sort
さらに、デフォルトのフィールド区切り文字は、スペースではなくスペースとスペースの間の遷移であるため、キーに先行スペースが含まれます。たとえば、最初の行の場合、最初のキーはですが、"Emily"
2番目のキー" Bedford"
はです。追加の-b
削除空のオプション:
sort -b -k2,2 -k1,1
b
キー実行仕様の最後にフラグを追加して、キーごとにこれを実行することもできます。
sort -k2b,2 -k1,1 <people.txt
ただし、覚えておくべきことの1つは、これらのフラグをキー仕様に追加するとグローバルフラグ(たとえば、-n
... -r
)がそのフラグに適用されなくなるため、キーごとのフラグとグローバルフラグを混在させないことが最善です。
答え2
GNUの場合はsort
これを行うことができますが、MacOSの場合はわかりません。
sort -k2,2 -k1 <people.txt
修正するコメントに基づいています。引用元man sort
:
-k, --key=KEYDEF
sort via a key; KEYDEF gives location and type
KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where
F is a field number and C a character position in the field; both are
origin 1, and the stop position defaults to the line's end.
答え3
あなたはこれを行うことができます
$ sort -k2,2 -k1,1 people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Mark Brown 46
Pete Brown 37
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Alice Villamor 50
Ana Villamor 44
まずは-k2,2
姓でソートしたいです。次に、k1,1
名前でソートします。
答え4
使用幸せ(以前のPerl_6)
UnicodeをソートしたいU&Lユーザーにこの回答を追加します。 Rakuには組み込みのUnicodeの高度なサポートがあり、この回答は(部分的に)作者がRakuの照合順序を理解するのに役立ちます。
「単項」比較演算子/ブロック(上部に注釈付き)または以下を含むバイナリブロックを使用して、1つの列(姓)に基づいてソートします。leg
「より小さい/同じ/より大きい」 ひも比較演算子。タイは「出会い」の順序を維持します(例:安定したソート):
~$ #`{ raku -e '.put for lines.sort: { .words[1] };' #unary block, OR binary block below: }
~$ raku -e '.put for lines.sort: { $^a.words[1] leg $^b.words[1] };' file
Tony Bedford 50
James Bedford 21
Emily Bedford 18
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
Simon Strange 62
John Strange 51
Ana Villamor 44
Alice Villamor 50
2つの列で並べ替えます(名前、姓、名前)。上部(コメント)にsort
ソートする要素の単項リストを提供します。以下の 2 番目の例: の間に「段落 OR」を使用して、2 つのleg
文字列比較演算子をより明示的に使用します。||
~$ #`{ raku -e '.put for lines.sort: { .words.[1], .words.[0] }; #list of unary elements, OR binary blocks below: }
~$ raku -e '.put for lines.sort: {$^a.words[1] leg $^b.words[1] || $^a.words[0] leg $^b.words[0] };' file
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Mark Brown 46
Pete Brown 37
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Alice Villamor 50
Ana Villamor 44
上記のRakuコードはこの質問のタイトルを満たしています。「2つのフィールドを並べ替えてみてください。2番目のフィールド、最初のフィールドです」。ただし、列が数値の場合は、数値で並べ替えるのではなく、次のように<=>
使用できます。leg
<=>
「宇宙船」オペレーター)。以下の例:
以下は、姓、逆年齢(最も古いものから置き換え、逆並べ替え$^b
に$^a
使用されます)、名前の3つの列を並べ替えます。したがって、ソートされた出力Simon Strange 62
の前に表示されますJohn Strange 51
。
Rakuには、cmp
型を検出してスマート比較を実行する拡張演算子があります(たとえば、文字列比較leg
と数値比較の比較<=>
)。以下の2番目の例ではサム cmp
比較結果は、最初の例とまったく同じソートされた出力を提供します。
~$ #`{ raku -e '.put for lines.sort: {$^a.words[1] leg $^b.words[1] || $^b.words[2] <=> $^a.words[2] || $^a.words[0] leg $^b.words[0] };' #OR with cmp operator below: }
~$ raku -e '.put for lines.sort: {$^a.words[1] cmp $^b.words[1] || $^b.words[2] cmp $^a.words[2] || $^a.words[0] cmp $^b.words[0] };' file
Tony Bedford 50
James Bedford 21
Emily Bedford 18
Fred Bloggs 22
Mark Brown 46
Pete Brown 37
Francis Chepstow 56
Stefan Heinz 52
Simon Strange 62
John Strange 51
Alice Villamor 50
Ana Villamor 44
最後に、「Binary Comparator Block」(上記)を使用すると、ソートメカニズムを正確に理解して制御できます。ただし、必要に応じて、上記の3つの列を並べ替える作業を次のコードに単純化できます。
~$ raku -e '.put for lines.sort: { ~.words[1], -.words[2], ~.words[0] };' file
Tony Bedford 50
James Bedford 21
Emily Bedford 18
Fred Bloggs 22
Mark Brown 46
Pete Brown 37
Francis Chepstow 56
Stefan Heinz 52
Simon Strange 62
John Strange 51
Alice Villamor 50
Ana Villamor 44
https://perl6advent.wordpress.com/2013/12/23/day-23-unary-sort/
https://docs.raku.org/言語/101-basics#Stable_sort
https://docs.raku.org/routine/sort
https://docs.raku.org/routine/cmp
https://perl6advent.wordpress.com/2013/12/23/day-23-unary-sort/
https://raku.org