RubyでCSVデータをリスト化して抽出する処理の解説

Uncategorized

久しぶりに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データをリスト化し、データを抽出する処理の実装例を紹介しました。
グループ化、日付の最古データ抽出、ヘッダー生成、データのハッシュ化、出力制御といったポイントを整理して解説しています。今後の実装に役立てていただければ幸いです。

タイトルとURLをコピーしました