- 締切済み
Rubyで配列をソートする
15(tab)5634(改行) 24(tab)4446(改行) 24(tab)8357(改行) 24(tab)3287(改行) 56(tab)5465(改行) 56(tab)1324(改行) 56(tab)7544(改行) 上記のように1行にtabで区切られた2つの数値が並んでいるテキストファイルがあります。 このファイルを、Rubyを使って1列目が同じ数字の行ごとにソートしたいのですが、できなくて困っています。 上の例でしたら、1列目が24の3行を2列目の数値をキーとしてソート、1列目が56の3行を2列目の数値をキーとしてソートするということです。 一行ずつ読み込んで、array = line.split(/\t/)でタブでくぎって配列に格納するスクリプトを書いていたのですが、どうしてもできないので、力を貸していただけないでしょうか。 よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- namboku
- ベストアンサー率50% (2/4)
ご質問から1列目は小さい順に並べられているものと仮定します。 また、入力データが"input.txt"というファイルに格納され、 出力データを"output.txt"にしているとすると、 以下のようなスクリプトで実行できると思います。 (字下げがなくなっているので、見にくいとは思いますが、ご了承ください) in1_file = open("input.txt","r") out1_file = open("output.txt","w") # 初期値設定 in1_ctr = 0 #入力件数 w_ctr = 0 #ソート件数 in1_key = nil #入力キー in1 = nil #入力した配列 in1_rec = Array.new #入力キー sv_key = nil #保存キー # キーブレイク時の処理 def s_break(in1_rec,out1_file) sort_rec = in1_rec.sort_by{|a| a_array = a.split("\t",-1) [a_array[1]] } sort_rec.each {|data| out1_file.print data,"\n" } end # 主処理 while (line1 = in1_file.gets) line1.chomp! in1 = line1.split("\t") in1_key = in1[0] in1_ctr += 1 # キーブレイク時 if ((in1_ctr != 1) && (sv_key != in1_key)) s_break(in1_rec,out1_file) w_ctr = 0 in1_rec = [] end sv_key = in1_key in1_rec[w_ctr] = line1 w_ctr += 1 end # 最終データの処理(入力データがある場合) if (in1_ctr != 0) s_break(in1_rec,out1_file) end # ファイルクローズ in1_file.close out1_file.close あるいは、1列目を第1のキー、2列目を第2のキーとして昇順に並べ替えてもよいのであれば、 以下のようなスクリプトになります。 in1_file = open("input.txt","r") out1_file = open("output.txt","w") in1_ctr = 0 in1_rec = Array.new sort_rec = Array.new while (line1 = in1_file.gets) line1.chomp! in1_rec[in1_ctr] = line1 in1_ctr += 1 end sort_rec = in1_rec.sort_by{|a| a_array = a.split("\t",-1) [a_array[0].to_i,a_array[1].to_i] } sort_rec.each {|data| out1_file.print data,"\n" } in1_file.close out1_file.close 上記で、"[a_array[0].to_i,a_array[1].to_i]"としている箇所が整数で1列目を第1キーに、同じく整数で2列目を第2キーに指定している部分です。ご質問の例では、1列目と2列目でそれぞれ数字の桁数が同じでしたので、仮に「文字列型」として並べ替えても良いのであれば、"[a_array[0],a_array[1]]"とすることもできます。
- n333
- ベストアンサー率0% (0/0)
1列目はソートしたくないということと理解しました。 (インデントされないようなので見難くてすみません) array = [] old = nil while line = gets group, key = line.chomp.split(/\t/) unless old == group array.sort_by{|a|a.to_f}.each do |k| puts [old,k].join("\t") end old = group array = [] end array << key end array.sort_by{|a|a.to_f}.each do |k| puts [old,k].join("\t") end
- notnot
- ベストアンサー率47% (4900/10359)
各カラムの数字の桁数が例示のように各行固定なら、 puts IO.readlines("ファイル名").sort でいいのでは? 各カラムが2文字4文字と固定長とは限らず、文字列としてで無く数値として比較しないといけないとすると、 puts IO.readlines("ファイル名").sort_by{|line| line.chomp.split(/\t/).map{|x| x.to_i }}
- sholmes
- ベストアンサー率81% (89/109)
正規表現でも文字列でも、\tメタ文字を用いて区切るやり方で問題無いと思いま すよ。 どのあたりでうまくいかない感じですか? 一例だけ http://ideone.com/Ii63o
- koko_u_u
- ベストアンサー率18% (216/1139)
array = line.split("\t") じゃね? と、勘で回答