在 Ruby 中将数组输出到 CSV

Posted

技术标签:

【中文标题】在 Ruby 中将数组输出到 CSV【英文标题】:Output array to CSV in Ruby 【发布时间】:2011-06-16 21:12:40 【问题描述】:

使用 Ruby 将 CSV 文件读入数组很容易,但我找不到任何关于如何将数组写入 CSV 文件的好的文档。谁能告诉我怎么做?

如果这很重要,我正在使用 Ruby 1.9.2。

【问题讨论】:

您的答案很好,但我敦促您不要使用 CSV。如果您的数据中没有制表符,则制表符分隔的文件更容易处理,因为它们不涉及太多的引用和转义等。如果您必须使用 CSV,当然,它们就是中断。 @Bill,CSV 模块巧妙地处理制表符分隔的文件以及实际的 csv 文件。 :col_sep 选项允许您将列分隔符指定为“\t”,一切都很好。 这里有更多关于 CSV 的信息docs.ruby-lang.org/en/2.1.0/CSV.html 在这个模块中使用 .tab 文件是我正在做的,因为不小心在 Excel 中打开它会打乱编码…… 【参考方案1】:

如果你有一组数据数组:

rows = [["a1", "a2", "a3"],["b1", "b2", "b3", "b4"], ["c1", "c2", "c3"]]

然后你可以把它写到一个文件中,我认为这要简单得多:

require "csv"
File.write("ss.csv", rows.map(&:to_csv).join)

【讨论】:

是的,但是每次都重写文件,而不是最后添加数据 @HumayunNaseer 我不需要将数据附加到 CSV 的情况,但您当然可以使用 mode: "a" 选项 File.write【参考方案2】:

我只写了一行。

rows = [['a1', 'a2', 'a3'],['b1', 'b2', 'b3', 'b4'], ['c1', 'c2', 'c3'], ... ]
csv_str = rows.inject([])  |csv, row|  csv << CSV.generate_line(row) .join("")
#=> "a1,a2,a3\nb1,b2,b3\nc1,c2,c3\n" 

执行上述所有操作在一行中保存到 csv。

File.open("ss.csv", "w") |f| f.write(rows.inject([])  |csv, row|  csv << CSV.generate_line(row) .join(""))

注意:

我认为将活动记录数据库转换为 csv 是这样的

CSV.open(fn, 'w') do |csv|
  csv << Model.column_names
  Model.where(query).each do |m|
    csv << m.attributes.values
  end
end

嗯@tamouse,如果不阅读 csv 源代码,这个要点对我来说有点令人困惑,但一般来说,假设你的数组中的每个散列具有相同数量的 k/v 对,并且键总是相同的订单(即,如果您的数据是结构化的),这应该做的事:

rowid = 0
CSV.open(fn, 'w') do |csv|
  hsh_ary.each do |hsh|
    rowid += 1
    if rowid == 1
      csv << hsh.keys# adding header row (column labels)
    else
      csv << hsh.values
    end# of if/else inside hsh
  end# of hsh's (rows)
end# of csv open

如果您的数据没有结构化,这显然是行不通的

【讨论】:

我使用 CSV.table 提取了一个 CSV 文件,进行了一些操作,删除了一些列,现在我想再次将生成的 Hash 数组作为 CSV 输出(真的是制表符分隔) .如何? gist.github.com/4647196 hmm...这个要点有点不透明,但是给定一个哈希数组,所有这些都具有相同数量的 k/v 对和相同的键,以相同的顺序... 谢谢,@boulder_ruby。那可行。数据是一个人口普查表,回顾它的要点是相当不透明的。 :) 它基本上是从原始人口普查表中提取某些列到一个子集中。 你在这里误用了inject,你真的想用map。此外,您不需要将空字符串传递给join,因为这是默认设置。所以你可以进一步缩小它:rows.map(&amp;CSV.method(:generate_line).join 您的第二个示例过于复杂,因为 CSV 库非常强大。 CSV.generate(headers: hsh.first&amp;.keys) |csv| hsh.each |e| csv &lt;&lt; e 生成一个等效的 CSV。【参考方案3】:

如果有人感兴趣,这里有一些单行代码(以及关于 CSV 中类型信息丢失的说明):

require 'csv'

rows = [[1,2,3],[4,5]]                    # [[1, 2, 3], [4, 5]]

# To CSV string
csv = rows.map(&:to_csv).join             # "1,2,3\n4,5\n"

# ... and back, as String[][]
rows2 = csv.split("\n").map(&:parse_csv)  # [["1", "2", "3"], ["4", "5"]]

# File I/O:
filename = '/tmp/vsc.csv'

# Save to file -- answer to your question
IO.write(filename, rows.map(&:to_csv).join)

# Read from file
# rows3 = IO.read(filename).split("\n").map(&:parse_csv)
rows3 = CSV.read(filename)

rows3 == rows2   # true
rows3 == rows    # false

注意:CSV 会丢失所有类型信息,您可以使用 JSON 来保留基本类型信息,或者使用详细(但更易于人工编辑)的 YAML 来保留所有类型信息——例如,如果您需要日期类型,这将成为 CSV 和 JSON 中的字符串。

【讨论】:

【参考方案4】:

基于@boulder_ruby 的回答,这就是我正在寻找的,假设us_eco 包含我的要点中的CSV 表。

CSV.open('outfile.txt','wb', col_sep: "\t") do |csvfile|
  csvfile << us_eco.first.keys
  us_eco.each do |row|
    csvfile << row.values
  end
end

更新了https://gist.github.com/tamouse/4647196的要点

【讨论】:

【参考方案5】:

我自己也在为此苦苦挣扎。这是我的看法:

https://gist.github.com/2639448:

require 'csv'

class CSV
  def CSV.unparse array
    CSV.generate do |csv|
      array.each  |i| csv << i 
    end
  end
end

CSV.unparse [ %w(your array), %w(goes here) ]

【讨论】:

顺便说一句,当心 JRuby 上的多维数组。 [ %w(your array), %w(goes here) ] 看起来不漂亮。 github.com/pry/pry/issues/568【参考方案6】:

到一个文件:

require 'csv'
CSV.open("myfile.csv", "w") do |csv|
  csv << ["row", "of", "CSV", "data"]
  csv << ["another", "row"]
  # ...
end

到一个字符串:

require 'csv'
csv_string = CSV.generate do |csv|
  csv << ["row", "of", "CSV", "data"]
  csv << ["another", "row"]
  # ...
end

这是 CSV 上的当前文档:http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html

【讨论】:

@David 这是文件模式。 “w”表示写入文件。如果您不指定此选项,它将默认为“rb”(只读二进制模式),并且在尝试添加到 csv 文件时会出现错误。有关 Ruby 中有效文件模式的列表,请参阅 ruby-doc.org/core-1.9.3/IO.html。 明白了。对于未来的用户,如果您希望每次迭代都不会覆盖之前的 csv 文件,请使用“ab”选项。 查看 Ruby 文件 IO 模式的答案:***.com/a/3682374/224707

以上是关于在 Ruby 中将数组输出到 CSV的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ruby 中将十进制值数组转换为 MAC 地址?

如何在 Android Studio 中将 CSV 文件解析为数组

如何在 Angular 中将动态 JSON 对象数组导出为 CSV?

如何在Ruby中将单词数组排序为字谜数组?

如何在Ruby中将数组数组转换为一个字符串[关闭]

在nodejs中将数组写入CSV