CSV ย่อมาจาก "Comma-Separated Values"
เป็นรูปแบบข้อมูลทั่วไปที่ประกอบด้วยแถวที่มีค่าคั่นด้วยเครื่องหมายจุลภาค ใช้สำหรับ export และ import ข้อมูล
ตัวอย่าง:
คุณสามารถ export contacts ของ Gmail เป็นไฟล์ CSV และ import กลับเข้ามาได้ด้วยรูปแบบเดียวกัน
ไฟล์ CSV 长这样:
id,name 1,chocolate 2,bacon 3,apple 4,banana 5,almonds
ตอนนี้คุณจะเรียนรู้วิธีใช้ Ruby CSV library เพื่ออ่านและเขียนไฟล์ CSV
การ Parse CSV ด้วย Ruby
Ruby มาพร้อม CSV library built-in
คุณอ่านไฟล์โดยตรงได้:
require 'csv'
CSV.read("favorite_foods.csv")
หรือคุณสามารถ parse string ที่มีข้อมูล CSV:
require 'csv'
CSV.parse("1,chocolate\n2,bacon\n3,apple")
ผลลัพธ์?
คุณได้ two-dimensional array ที่ทุก entry คือหนึ่งแถวในตาราง
长这样:
[ ["id", "name"], ["1", "chocolate"], ["2", "bacon"], ["3", "apple"], ["4", "banana"], ["5", "almonds"] ]
คุณสามารถใช้ array indices เช่น data[1][1] เพื่อทำงานกับข้อมูลนี้
แตมีวิธีที่ดีกว่า!
CSV Options
หากไฟล์ของคุณมี headers คุณสามารถบอก parser ให้ใช้ได้
แบบนี้:
table = CSV.parse(File.read("cats.csv"), headers: true)
ตอนแทนที่จะได้ multi-dimensional array คุณได้ CSV Table object
คำอธิบาย:
"
CSV::Tableเป็นโครงสร้างข้อมูลสองมิติสำหรับ represent เอกสาร CSV Tables อนุญาตให้คุณทำงานกับข้อมูลตามแถวหรือคอลัมน์ จัดการข้อมูล และแม้แต่แปลงผลลัพธ์กลับเป็น CSV"
เมื่อมี table หนึ่งแล้ว คุณสามารถดึงข้อมูลที่ต้องการจากแถวไหนก็ได้
ตัวอย่าง:
table[0]["id"] # "1" table[0]["name"] # "chocolate"
ที่นี่ 0 คือแถวแรก id และ name คือชื่อคอลัมน์
มีสองโหมดของ table:
- by_col
- by_row
ด้วยการเปลี่ยน table mode (row เป็นค่าเริ่มต้น) คุณสามารถมองข้อมูลจากมุมมองต่างๆ ได้
ตัวอย่าง:
table.by_col[0] # ["1", "2", "3", "4", "5"] table.by_col[1] # ["chocolate", "bacon", "apple", "banana", "almonds"]
ที่นี่ 0 คือคอลัมน์แรก 1 คือคอลัมน์ที่สอง
เมธอดทั้งสองนี้คืน สำเนาของ table
หากต้องการเปลี่ยนแปลง table ต้นฉบับ ให้ใช้เมธอด by_col! และ by_row!
สิ่งนี้จะ memory-efficient กว่าเพราะไม่สร้างสำเนาของ table
วิธีใช้ CSV Converters
คุณอาจสังเกตว่าเราได้คอลัมน์ id เป็นอาร์เรย์ของ strings
ถ้าต้องการ Integers ล่ะ?
คุณได้มันโดยเรียก to_i บนแต่ละ string…
แตมี shortcut!
Ruby CSV library implement ที่เรียกว่า converters
Converter จะแปลงค่าให้คุณอัตโนมัติ
ตัวอย่าง:
CSV.parse("1,2,3,4,5") # [["1", "2", "3", "4", "5"]]
CSV.parse("1,2,3,4,5", converters: :numeric) # [[1, 2, 3, 4, 5]]
มี built-in converters 6 ตัว:
- Integer
- Float
- Numeric (Float + Integer)
- Date
- DateTime
- All
แตคุณยังสร้าง custom converters เองได้
วิธีทำ:
CSV::Converters[:symbol] = ->(value) { value.to_sym rescue value }
คุณสามารถ ใช้ converter ใหม่แบบนี้:
CSV.parse("a,b,c", headers: false, converters: :symbol) # [[:a, :b, :c]]
วิธีสร้างไฟล์ CSV ใหม่
นอกจาก parse และอ่าน CSV แบบต่างๆ แล้ว คุณยังสร้าง CSV จากศูนย์ได้
วิธีง่าย:
cats = [
[:blue, 1],
[:white, 2],
[:black_and_white, 3]
]
cats.map { |c| c.join(",") }.join("\n")
คุณยังใช้เมธอด generate ได้:
CSV.generate do |csv| csv << [:blue, 1] csv << [:white, 2] csv << [:black_and_white, 3] end
สิ่งนี้เตรียมข้อมูลให้อยู่ในรูปแบบที่ถูกต้อง
หากต้องการเขียนลงไฟล์ คุณต้องใช้อย่าง File.write("cats.csv", data) หรือแทน generate ใช้ open พร้อมชื่อไฟล์และ write mode
แบบนี้:
CSV.open("cats.csv", "w") do |csv|
csv << [:white, 2]
end
ตอนนี้คุณมีไฟล์ CSV ใหม่!
CSV Gems และ Performance
Built-in library ใช้ได้ดีและทำงานเสร็จ
แตคุณยังหา CSV parsing gems หลายตัวที่มีฟีเจอร์ต่างๆ
เช่น gem smarter_csv จะแปลง CSV data เป็น array of hashes
ตัวอย่าง:
require 'smarter_csv'
IntegerConverter = Object.new
def IntegerConverter.convert(value)
Integer(value)
end
SmarterCSV.process('testing.csv', value_converters: { id: IntegerConverter })
# [{:id=>1, :name=>"a"}, {:id=>2, :name=>"b"}, {:id=>3, :name=>"c"}]
นี่คือการเปรียบเทียบประสิทธิภาพ:
Comparison: CSV: 112.9 i/s Smarter CSV: 21.7 i/s - 5.21x slower Tabular: 17.3 i/s - 6.52x slower
สรุป
คุณเรียนรู้วิธีอ่านและเขียนไฟล์ CSV ใน Ruby แล้ว! ยังเรียนรู้เกี่ยวกับ converters และ Ruby gems ทางเลือกสำหรับประมวลผล CSV data
หากต้องการ ประมวลผลไฟล์ CSV ใหญ่ (> 10MB) คุณอาจอยากใช้เมธอด CSV.foreach(file_name) พร้อม block จะอ่านทีละแถวและใช้หน่วยความจำน้อยมาก
กรุณาแชร์บทความนี้ให้ผู้คนอีกมากขึ้นค้นพบได้!