2 列目で、並べ替えをするには?
HIDEO
HIDEO
ATOMRSS
  • コード求むID: 305
  • 登録日時:  2008/07/21 01:00
  • 最終更新日時: 2008/09/23 23:11
  • アクセス数: 1655
  • タグ: 
  • codeなにがしブックマークに追加する 0 users
  • このページを del.icio.us に追加
  • このページをはてなブックマークに追加

こんばんは、
お世話になります。

どの言語で実現できるか わかりませんが、
スクリプトを使用して(シェル,awk,perlなど)

AA 55 AA AA
BB 44 BB BB
CC 33 CC CC
DD 22 DD DD
EE 11 EE EE

EE 11 EE EE
DD 22 DD DD
CC 33 CC CC
BB 44 BB BB
AA 55 AA AA
に並べ変える事は
できないでしょうか?



 

コメント

  • ゲスト
  • 1:ゲスト (み)
  • 2008/07/21 01:10

シェルというか、sortコマンドで
sort +1 でできますよ。
ただ、区切り文字がデフォルトだとタブだったかな?
sort -d" +1 とかしないといけないかも。

GJGJGJGJ

  • l-w-i
  • 2:l-w-i
  • 2008/07/21 01:37

sort +1 でできますよ。

↑そうですよね。

と思ったら、僕のメインマシンであるFedora 9に入っているsortではエラーになりました。

% sort +1 <file>
sort: オープン失敗: +1: そのようなファイルやディレクトリはありません

% sort --v
sort (GNU coreutils) 6.10
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and Paul Eggert.
僕が業務で使っているSolarisのsortではうまくいくような気がしていたのですが...

代わりに--keyというオプションが使えました。

% sort --key=2 <file>
EE 11 EE EE 
DD 22 DD DD
CC 33 CC CC
BB 44 BB BB
AA 55 AA AA

GJGJGJGJGJ

  • HIDEO
  • 3:HIDEO
  • 2008/07/21 09:18

回答ありがとうございました。

GJGJGJGJ

  • ゲスト
  • 4:ゲスト (BLUEPIXY)
  • 2008/07/21 15:12

Perl で、
スクリプトをsample.pl
入力ファイルをdata.txt
とするとき
sample.pl data.txt

#sample.pl
print map $_->[0], sort{ $a->[1] <=> $b->[1] } map [$_, (split)[1]],<> ;

GJGJGJGJGJ

  • HIDEO
  • 5:HIDEO
  • 2008/07/25 01:19

こんばんは、

date.txtの中身をリードしているのは
どの部分でしょうか?
(file open しなくても 
 ファイルをリードできているのが
 不思議に思います)

GJGJGJGJ

  • ゲスト
  • 6:ゲスト (BLUEPIXY)
  • 2008/07/26 02:44

5>date.txtの中身をリードしているのはどの部分でしょうか?
「<>」がそうです。
引数にファイル名を渡しているので、これで読み込めます。

GJGJGJGJGJ

>>BLUEPIXY
perlでと言われて素直にこうかなと思いましたが
perl -e 'print sort {(split /,$a)[1] <=> (split /,$b)[1]} <>' data
そんな方法が。

恥ずかしながらsplitが引数なしでそんな動作するとは知りませんでした。めちゃめちゃ便利ですねぇ。

GJGJGJGJ

  • ゲスト
  • 8:ゲスト (BLUEPIXY)
  • 2008/07/26 17:57

7>そんな方法
よく使われる方法です。
シュワルツ変換とか言われていると思います。
ソートの比較手続きで、その度にキーを取り出すような操作がムダなので、
キーとデータの一時表を作成して、そちらでソートを行います。

7>splitが引数なしでそんな動作
split で、パターンを省略した場合に用いられるパターンは、
\t\n]+ です。
大抵の空白文字で区切られたフィールドは、これでいけるので、省略できます。

GJGJGJ

>ソートの比較手続きで、その度にキーを取り出すような操作がムダなので、
なるほどです。

>>1,2
今使ってるmacのsort(5.93)でも+2だとだめで、
sort --key=2 data.txt

#sort -k data.txt
でいけました。


あとスレ主さん、1,2の方法だと文字列としてソートですが4,7だと数値でソートなので必要があれば考慮しといてください。
4と10をソートする時に文字列で比較するのと数値で比較するのでは順序が変わりますので。
・シェルのソート
デフォルト:文字列
-nオプションつき:数値

perlの比較関数中で使ってる演算子は
<=>演算子:数値比較
cmp演算子:文字列比較
です。

GJGJGJGJ

  • HIDEO
  • 10:HIDEO
  • 2008/07/26 23:09

こんばんは、
お世話になります。

print map $_->[0], sort{ $a->[1] <=> $b->[1] map [$_, (split)[1]],<> 

は、右から左に処理されるのでしょうか?
もし、右から左に処理されるのが、正しいならば、
なぜ、この場合は、右から左に処理されるのでしょうか?

ここで、使用されている 「 ,」 の役割は,何でしょうか?

map [$_, (split)[1]] で,
使用されている 「,」は,どのような役割でしょうか?




GJGJGJGJ

  • ゲスト
  • 11:ゲスト (BLUEPIXY)
  • 2008/07/27 02:19

10>右から左に処理されるのでしょうか?
全体として「右から左に処理される」と考えて良いです。

10>「 ,」 の役割は,何でしょうか?
map の構文として
map 評価すべき式, 適用すべきリスト
なので、そのための「,」です。

map $_->[0], sort{ $a->[1] <=> $b->[1] map [$_, (split)[1]],<> 
は、
式:$_->[0]
リスト:sort{ $a->[1] <=> $b->[1] map [$_, (split)[1]],<>

map [$_, (split)[1]],<>
は、
式:[$_, (split)[1]]
リスト(無名配列として読み込んだファイル全体):<>
と言う風になっています。
式の引数の評価順としてそうなります。
(そのために、便宜上右から左に思える)
つまり
map(式, map(式, リスト))
のように呼び出しがネストしているということ。

10>「,」は,どのような役割でしょうか?
は、無名配列のリファレンス(を返す?)の構文です。
@array 要素1, 要素2 )
のような意味で
$arrayr 要素1, 要素2 ]
と書きます。
要するに、配列の要素を区切るためのカンマです。

配列のリファレンスへのアクセスは
$$arrayr[0]; #要素1
$arrayr->[1]; #このようにも書ける、要素2
の様にします。

GJGJGJ

  • HIDEO
  • 12:HIDEO
  • 2008/07/27 07:08

回答いただきありがとう
ございました.

GJGJGJGJ

  • sion
  • 13:sion
  • 2008/08/18 13:33

「シュワルツ変換より高速なソート手法」というのを使って、こんな風にも書けるようです。

% perl -e 'my @data = <>; my @idx = map {(split)[1]} @data; print @data[ sort { $idx[$a] <=> $idx[$b] } 0 .. $#idx ];' data.txt
今回の前処理は《半角空白で区切られた2番目の要素を取り出す》程度で、データ件数が5件のサンプルなので、差はほとんどありませんが…

GJGJGJGJGJ

  • HIDEO
  • 15:HIDEO
  • 2008/09/23 20:44

こんばんは、

すいませんが、

map $_->[0], sort{ $a->[1] <=> $b->[1] map [$_, (split)[1]],<> 

(split)[1]
とは
どのように動作するのでしょうか?

GJGJGJGJ

  • ゲスト
  • 16:ゲスト (BLUEPIXY)
  • 2008/09/23 22:58

15>(split)[1]とはどのように動作するのでしょうか?
split は、split [/区切りパターン/ [, 処理文字列]]
の様に書いて(上記の[] は省略できることを表します)
処理文字列を区切りパターンで分割したリストを返します。
パターンを省略した時には、コメント8で言及しているパターンで
処理文字列を省略した時には、$_ を処理します。
つまり、処理文字列が
"AA 55 AA AA"
の時
("AA", "55", "AA", "AA")
のようなリストを作ります。
リストは、ほぼ配列と同じと考えて良いので
("AA", "55", "AA", "AA")[1]
は、"55" を取り出すことになります。
つまり「入力したデータ行それぞれから2列(カラム)目を取り出す。」ということです。

#テスト用プログラム
$pos = tell(DATA);

while(<DATA>){
	$result = (split)[1];
	print "$result\n";
}
print "\n";

seek(DATA, $pos, 0);#巻き戻し

print "test:('AA', '55', 'AA', 'AA')[1]\t";
$result = ('AA', '55', 'AA', 'AA')[1];
print "$result\n\n";

while(<DATA>){
	@list = split(/[\s\t\n]+/, $_);
	print "(" . join(",", @list) . ")\n";
	print "@list[1]\t$list[1]\n";
}

__DATA__
AA 55 AA AA 
BB 44 BB BB 
CC 33 CC CC 
DD 22 DD DD 
EE 11 EE EE 

GJGJGJGJGJGJ

前へ 1 次へ

プレゼン公開・共有サイト handsOut.jp チーム・マイナス6% - みんなで止めよう温暖化

ブックマークコメント