Computer >> Máy Tính >  >> Lập trình >> Ruby

Cách đọc và phân tích cú pháp tệp CSV với Ruby

CSV là viết tắt của “Giá trị được phân tách bằng dấu phẩy”.

Đó là một định dạng dữ liệu phổ biến bao gồm các hàng có các giá trị được phân tách bằng dấu phẩy. Nó được sử dụng để xuất và nhập dữ liệu.

Ví dụ :

Bạn có thể xuất danh bạ Gmail của mình dưới dạng tệp CSV và bạn cũng có thể nhập chúng bằng cùng một định dạng.

Đây là tệp CSV trông như thế nào :

id,name
1,chocolate
2,bacon
3,apple
4,banana
5,almonds

Bây giờ bạn sẽ tìm hiểu cách sử dụng thư viện Ruby CSV để đọc và ghi tệp CSV.

Ruby CSV Parsing

Ruby đi kèm với một thư viện CSV tích hợp sẵn.

Bạn có thể đọc tệp trực tiếp :

require 'csv'

CSV.read("favorite_foods.csv")

Hoặc bạn có thể phân tích cú pháp chuỗi với dữ liệu CSV :

require 'csv'

CSV.parse("1,chocolate\n2,bacon\n3,apple")

Kết quả?

Bạn nhận được một mảng hai chiều trong đó mỗi mục nhập là một hàng trong bảng.

Có vẻ như thế này :

[
  ["id", "name"],
  ["1", "chocolate"],
  ["2", "bacon"],
  ["3", "apple"],
  ["4", "banana"],
  ["5", "almonds"]
]

Bạn có thể sử dụng các chỉ số mảng như data[1][1] để làm việc với dữ liệu này.

Nhưng có một cách tốt hơn!

Tùy chọn CSV

Nếu tệp của bạn có các tiêu đề, bạn có thể yêu cầu trình phân tích cú pháp CSV sử dụng chúng.

Như thế này :

table = CSV.parse(File.read("cats.csv"), headers: true)

Bây giờ thay vì một mảng nhiều chiều, bạn nhận được một đối tượng Bảng CSV.

Đây là mô tả :

“Một CSV::Table là cấu trúc dữ liệu hai chiều để đại diện cho các tài liệu CSV. Các bảng cho phép bạn làm việc với dữ liệu theo hàng hoặc cột, thao tác dữ liệu và thậm chí chuyển đổi kết quả trở lại CSV. ”

Với một trong các bảng này, bạn có thể lấy dữ liệu mình cần từ bất kỳ hàng nào.

Ví dụ :

table[0]["id"]
# "1"

table[0]["name"]
# "chocolate"

Đây 0 là hàng đầu tiên, id &name là các tên cột.

Có hai chế độ bảng :

  • by_col
  • by_row

Bằng cách thay đổi chế độ bảng (row theo mặc định) bạn có thể xem dữ liệu từ các góc độ khác nhau.

Ví dụ :

table.by_col[0]
# ["1", "2", "3", "4", "5"]

table.by_col[1]
# ["chocolate", "bacon", "apple", "banana", "almonds"]

Đây 0 là cột đầu tiên, 1 là cột thứ hai.

Hai phương thức này trả về bản sao của bảng .

Nếu bạn muốn thay đổi bảng gốc thì bạn có thể sử dụng by_col! &by_row! phương pháp.

Điều này sẽ tiết kiệm bộ nhớ hơn vì không có bản sao của bảng được tạo.

Cách sử dụng Bộ chuyển đổi CSV

Bạn có thể nhận thấy rằng chúng tôi đã nhận được id của mình cột dưới dạng một mảng chuỗi.

Điều gì xảy ra nếu chúng ta cần Số nguyên?

Bạn có thể lấy chúng bằng cách gọi to_i trên mỗi chuỗi…

Nhưng có một con đường tắt!

Thư viện Ruby CSV triển khai một thứ được gọi là trình chuyển đổi .

Công cụ chuyển đổi sẽ tự động chuyển đổi các giá trị cho bạn.

Ví dụ :

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]]

Có 6 trình chuyển đổi tích hợp sẵn :

  • Số nguyên
  • Nổi
  • Numeric (Float + Integer)
  • Ngày tháng
  • DateTime
  • Tất cả

Nhưng bạn cũng có thể tạo bộ chuyển đổi tùy chỉnh của riêng mình.

Đây là cách thực hiện :

CSV::Converters[:symbol] = ->(value) { value.to_sym rescue value }

Bạn có thể sử dụng trình chuyển đổi mới của mình như thế này :

CSV.parse("a,b,c", headers: false, converters: :symbol)

# [[:a, :b, :c]]

Cách tạo tệp CSV mới

Ngoài khả năng phân tích cú pháp và đọc tệp CSV theo nhiều cách khác nhau, bạn cũng có thể tạo CSV từ đầu.

Đây là cách dễ dàng :

cats = [
  [:blue, 1],
  [:white, 2],
  [:black_and_white, 3]
]

cats.map { |c| c.join(",") }.join("\n")

Bạn cũng có thể sử dụng generate phương pháp:

CSV.generate do |csv|
  csv << [:blue, 1]
  csv << [:white, 2]
  csv << [:black_and_white, 3]
end

Điều này chuẩn bị cho dữ liệu ở định dạng phù hợp.

Nếu bạn muốn ghi vào một tệp, bạn sẽ phải sử dụng một cái gì đó như File.write("cats.csv", data) hoặc thay vì generate bạn có thể sử dụng open với tên tệp và chế độ ghi được bật.

Như thế này :

CSV.open("cats.csv", "w") do |csv|
  csv << [:white, 2]
end

Bây giờ bạn có một tệp CSV mới!

Đá quý và hiệu suất CSV

Thư viện tích hợp sẵn rất ổn và nó sẽ hoàn thành công việc.

Nhưng bạn cũng có thể tìm thấy một số đá quý phân tích cú pháp CSV với các tính năng khác nhau.

Ví dụ:smarter_csv gem sẽ chuyển đổi dữ liệu CSV của bạn thành một mảng băm.

Ví dụ :

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"}]

Đây là so sánh hiệu suất :

Comparison:
       CSV:      112.9 i/s
Smarter CSV:     21.7 i/s - 5.21x  slower
   Tabular:      17.3 i/s - 6.52x  slower

Tóm tắt

Bạn đã học cách đọc và ghi tệp CSV trong Ruby! Bạn cũng đã tìm hiểu về trình chuyển đổi và đá quý Ruby thay thế để xử lý dữ liệu CSV của bạn.

Nếu bạn muốn xử lý các tệp CSV lớn (> 10MB) bạn có thể muốn sử dụng CSV.foreach(file_name) phương pháp với một khối. Thao tác này sẽ đọc từng hàng một và sử dụng ít bộ nhớ hơn rất nhiều.

Hãy chia sẻ bài viết này để nhiều người có thể tìm thấy nó!