如何将CSV文件的列导入到Ruby数组中?
我的目标是将一列CSV文件导入到Ruby数组中。这是一个自包含的Ruby脚本,而不是应用程序。我将在终端中运行脚本并获取输出。如何将CSV文件的列导入到Ruby数组中?
我无法找到导入文件的最佳方式,并找到将文件名称动态插入该代码行的最佳方法。文件名每次都会有所不同,并且会被用户传入。我正在使用$stdin.gets.chomp
向用户询问文件名,并将其设置为file_name
。
有人可以帮助我吗?这是我对脚本的这部分有什么:
require 'csv'
zip_array = CSV.read("path/to/file_name.csv")
我需要能够在上面插入适当的文件路径。它是否正确?我怎么在那里得到那个路径名?也许我需要完全重新构建我的脚本,但有关如何执行此操作的任何建议?
首先,你需要从$stdin.gets.chomp
指派返回值给一个变量:
foo = $stdin.gets.chomp
这将输入的输入端分配到foo
。
你并不需要使用$stdin
不过,因为gets
将默认使用标准输入通道:
foo = gets.chomp
在这一点上使用变量作为read
参数:
zip_array = CSV.read(foo)
这些都是基本的编码,并涵盖在任何语言的介绍书中。
我想这里有两个问题。首先是从命令行获取用户输入。通常的做法是使用ARGV
。在您的程序中,您可以执行file_name = ARGV[0]
,以便用户可以在命令行上输入ruby your_program.rb path/to/file_name.csv
。
接下来是关于阅读CSV。使用CSV.read
将采用整个CSV,而不仅仅是一个列。如果你想选择很多的一列,你可能会更好做:
zip_array = []
CSV.foreach(file_name) { |row| zip_array << row[whichever_column] }
好了,第一个问题:
一个)的文件名会在每次运行不同的(我假定这将永远是一个CSV文件,对吧?)
你可以通过创建一个文件夹,说你的Ruby脚本中的input_data解决这个问题。然后执行:
Dir.glob('input_data/*.csv')
这将生成一个以CSV结尾的文件夹内的所有文件的数组。如果我们假设会出现在该文件夹的时间(使用不同的名称)只有1个文件,我们可以这样做:
file_name = Dir.glob('input_data/*.csv')[0]
这样你会动态获取的文件路径,无论该文件是什么命名。如果CSV文件是相同的目录中的Ruby脚本中,你可以这样做:
Dir.glob('*.csv')[0]
现在,进口只有1列到一个Ruby阵列(让我们假设它是第一列):
require 'csv'
array = []
CSV.foreach(file_name) do |csv_row|
array << csv_row[0] # [0] for the first column, [1] for the second etc.
end
如果您的CSV文件包含标头,该怎么办?假设你的列名是'Total'。你可以这样做:
require 'csv'
array = []
CSV.foreach(file_name, headers: true) do |csv_row|
array << csv_row['Total']
end
现在,如果你的列是第一列不要紧,第三等,只要它有一个名为“总计”栏头,红宝石会发现它。
CSV.foreach逐行读取文件,适用于大文件。 CSV.read将立即读取,但使用它可以使您的代码更加简洁:
array = CSV.read(, headers: true).map do |csv_row|
csv_row['Total']
end
希望这对我有所帮助。
要求输入的程序通常是非常烦人的。为什么不让文件名成为命令行参数?这些都可以在'ARGV'中找到。 – tadman 2014-09-23 19:01:54
如果该文件(无关紧要)将成为程序文件夹中唯一的csv文件,则可以使用Dir.glob(“*。csv”)[0]。这样你就不必担心这个名字会一直在改变。 – daremkd 2014-09-23 19:19:07