アプリ版:「スタンプのみでお礼する」機能のリリースについて

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/)でタブでくぎって配列に格納するスクリプトを書いていたのですが、どうしてもできないので、力を貸していただけないでしょうか。
よろしくお願いします。

A 回答 (5件)

 ご質問から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#保存キー

# キーブレイク時の処理
defs_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.printdata,"\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]]"とすることもできます。

参考URL:http://www003.upp.so-net.ne.jp/NAMBOKU/ruby/ruby …
    • good
    • 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
    • good
    • 0

各カラムの数字の桁数が例示のように各行固定なら、


puts IO.readlines("ファイル名").sort
でいいのでは?
各カラムが2文字4文字と固定長とは限らず、文字列としてで無く数値として比較しないといけないとすると、
puts IO.readlines("ファイル名").sort_by{|line| line.chomp.split(/\t/).map{|x| x.to_i }}
    • good
    • 0

正規表現でも文字列でも、\tメタ文字を用いて区切るやり方で問題無いと思いま


すよ。
どのあたりでうまくいかない感じですか?

一例だけ
http://ideone.com/Ii63o
    • good
    • 0

array = line.split("\t") じゃね?


と、勘で回答
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!