通过CSV :: Rows

时间:2019-09-25 22:22:25

标签: ruby-on-rails arrays ruby csv

我要开始说我仍在学习红宝石。

我正在编写一个脚本以解析.csv并识别数据集中可能存在的重复记录。

我有一个带标头的.csv文件,因此我正在解析数据,以便可以使用标头标题访问每一行,例如:

@contact_table = CSV.parse(File.read("app/data/file.csv"), headers: true)

# Prints all last names in table
puts contact_table['last_name']

我正在尝试遍历表中的每一行,并确定我当前正在遍历的姓氏是否类似于下一个姓氏,但是这样做很麻烦。我想我的处理方式就像是数组一样,但是我检查了类型,它是CSV :: Row。

示例(这不起作用):

@contact_table.each_with_index do |c, i|
  puts "first contact is #{c['last_name']}, second contact is #{c[i + 1]['last_name']}"
end

我意识到这不是这样,因为表不是数组,而是CSV :: Row,就像我之前提到的那样。有什么方法可以做到这一点?我现在真的很空白。

我的csv看起来像这样:

id,first_name,last_name,company,email,address1,address2,zip,city,state_long,state,phone
1,Donalt,Canter,Gottlieb Group,dcanter0@nydailynews.com,9 Homewood Alley,,50335,Des Moines,Iowa,IA,515-601-4495
2,Daphene,McArthur,"West, Schimmel and Rath",dmcarthur1@twitter.com,43 Grover Parkway,,30311,Atlanta,Georgia,GA,770-271-7837

3 个答案:

答案 0 :(得分:2)

@contact_table应该是CSV::Table,它是CSV::Row的集合,因此在此:

@contact_table.each_with_index do |c, i|
  ...
end

cCSV::Row。这就是c['last_name']起作用的原因。问题是在这里:

c[i + 1]['last_name']

您正在查看c(单行)而不是@contact_table,如果您说:

@contact_table[i + 1]['last_name']

那么您将得到下一个姓氏,或者当c是最后一行时,会出现一个例外,因为@contact_table[i+1]将是nil

此外,在迭代过程中,c当前(或第(i+1))行,并且不一定总是第一行。

答案 1 :(得分:1)

您的用例是什么?好像是学校的项目?

我建议使用for_each而不是解析(请参阅this comparison)。我可能为此使用Set

  • 在解析文件范围之外(即,在解析代码上方)创建一个Set。我们称之为rows
  • 在每次迭代期间调用rows.include?(row)来解析文件
    • 如果true,则表示您有重复项
    • 如果为false,则调用rows.add(row)将新行添加到集合中

您还可以只使用必须与众不同的列(例如row.field(:some_column_name))中的单个值(例如电子邮件或电话号码)来填充集合,并对此进行相同的包含检查。

(如果这是用于真实应用程序,请不要这样做。请改用模型validations。)

答案 2 :(得分:0)

我将使用#read而不是#parse并执行以下操作:

require 'csv'
LASTNAME_INDEX = 2
data = CSV.read('data.csv')

data[1..-1].each_with_index do |row, index|
  puts "Contact number #{index + 1} has the following last name : #{row[LASTNAME_INDEX]}"
end

#~> Contact number 1 has the following last name : Canter
#~> Contact number 2 has the following last name : McArthur