久しぶりにRubyを書く機会があったので、忘れないようにまとめてみました。
CSVデータをリスト化し、データ抽出する処理の実装例です。
今回のCSVデータにはヘッダーがなく、空データには”null”という文字列が使われていたため、その対処方法も合わせて紹介します。
Ω1文字コードの違いによるデータの分割方法やエンコードの考慮についても触れています。
1. CSVデータのリスト化
まずは、CSVデータをリスト化する方法です。データは文字列として受け取り、改行コードで分割した後、各行をカンマで区切って配列に変換します。
data = "田中,30,東京\n鈴木,25,大阪\n佐藤,40,名古屋\n高橋,28,福岡"
list = CSV.parse(data)
puts list.inspect
出力結果
[["田中", "30", "東京"], ["鈴木", "25", "大阪"], ["佐藤", "40", "名古屋"], ["高橋", "28", "福岡"]]
文字コードの違いについて
Windows環境では改行コードが\r\n
(CRLF)、Unix系では\n
(LF)が使われます。文字コードの違いによってデータの分割がうまくいかない場合があります。RubyではString#split
メソッドで改行コードを指定できます。
list = data.split(/\r\n|\n/).map { |row| row.split(",") }
もし文字コードの変換が必要な場合は、次のようにString#encode
メソッドを使います。
data = data.encode("UTF-8", "Windows-31J")
2. グループIDとメンバーIDごとのデータ抽出
CSVデータに含まれるグループIDとメンバーIDの組み合わせごとにデータを集約し、最も古いデータのみを残す方法です。
require 'date'
list = [
["1", "101", "2023/04/01", "田中"],
["1", "101", "2023/05/01", "田中"],
["1", "102", "2023/06/01", "鈴木"],
["2", "201", "2023/03/01", "佐藤"],
["2", "201", "2023/02/01", "佐藤"],
["3", "301", "2023/07/01", "高橋"]
]
filtered_list = list.group_by { |row| [row[0], row[1]] }
.map { |key, group| group.min_by
{ |row| Date.parse(row[2]) } }
puts filtered_list.inspect
出力結果
[["1", "101", "2023/04/01", "田中"],
["1", "102", "2023/06/01", "鈴木"],
["2", "201", "2023/02/01", "佐藤"],
["3", "301", "2023/07/01", "高橋"]]
3. ヘッダーの生成
CSVデータのヘッダーを生成する方法です。
固有のヘッダーの他、番号付きのヘッダーが存在したため、それに対応する方法を考えました。
(マネージャー01名前、マネージャー02名前、等)
グループごとに複数の項目を持つ場合、ヘッダーを動的に作成できます。
num_managers = 10
base_headers = ["GroupID", "MemberID", "Date", "Name"]
manager_headers = (1..num_managers).flat_map { |i| ["Manager#{i}_ID", "Manager#{i}_Name"] }
headers = base_headers + manager_headers
puts headers.inspect
出力結果
["GroupID", "MemberID", "Date", "Name", "Manager1_ID", "Manager1_Name", ..., "Manager10_ID", "Manager10_Name"]
4. ヘッダーとデータの結合
生成したヘッダーとデータを結合してハッシュ形式に変換する方法です。
filtered_list.map do |row|
base_data = base_headers.each_with_index.to_h { |header, index| [header, row[index]] }
base_data
end
出力結果
{"GroupID"=>"1", "MemberID"=>"101", "Date"=>"2023/04/01", "Name"=>"田中"}
5. 最大出力数の制御
データの最大出力数を制限する方法です。RubyではArray#first
メソッドを使って出力数を制御できます。
max_output_size = 2
limited_list = filtered_list.first(max_output_size)
puts limited_list.inspect
出力結果
[["1", "101", "2023/04/01", "田中"], ["1", "102", "2023/06/01", "鈴木"]]
まとめ
今回はRubyでCSVデータをリスト化し、データを抽出する処理の実装例を紹介しました。
グループ化、日付の最古データ抽出、ヘッダー生成、データのハッシュ化、出力制御といったポイントを整理して解説しています。今後の実装に役立てていただければ幸いです。