Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

อ่านและ Parse ไฟล์ CSV ด้วย Ruby อย่างง่ายดาย

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 จะอ่านทีละแถวและใช้หน่วยความจำน้อยมาก

กรุณาแชร์บทความนี้ให้ผู้คนอีกมากขึ้นค้นพบได้!