描述
在 ruby 中读取文件 csv。
我有一个 csv 文件 with this content
longitude,latitude,phone 13,139.7113134,35.56712836,0311112222
我读取了文件 csv。
- 我得到的数据不是预期的电话号码
代码
uploaded_io = params[:rooms][:file]
rooms_table = CSV.table(uploaded_io.tempfile, encoding: "UTF-8")
rooms_table.each_with_index do |row, i|
p row
end
puts row:
#<CSV::Row longitude:139.7113134 latitude:35.56712836 phone:52728978 >
我不明白 value phone number 在哪里?我希望电话号码是
0311112222
而不是 52728978
最佳答案
发生这种情况的原因是,per the docs , CSV.table
是:
A shortcut for:
CSV.read( path, { headers: true, converters: :numeric, header_converters: :symbol }.merge(options) )
注意 converters: :numeric
,它告诉它自动(尝试)将数字字段转换为数字。当然,电话号码并不是真正的数字,而是一串数字。
如果您不需要任何转换,您可以将converters: nil
作为CSV.table
的选项传递。
假设您确实希望:numeric
转换器仍然在其他字段上运行,但是,您需要定义自己的转换器。转换器是一个带有两个参数的 Proc:一个字段值和一个(可选的)FieldInfo 对象。您的转换器可能如下所示:
NUMERIC_EXCEPT_PHONE_CONVERTER = lambda do |value, field_info|
if field_info.header == :phone
value
else
CSV::Converters[:float].call(
CSV::Converters[:integer].call(value))
end
end
然后您可以通过将它作为 converters:
选项传递给 CSV.table
来使用它,这将覆盖默认的 converters: :numeric
:
rooms_table = CSV.table("data.csv", encoding: "UTF-8", converters: NUMERIC_EXCEPT_PHONE_CONVERTER)
p rooms_table[0]
# => #<CSV::Row longitude:139.7113134 latitude:35.56712836 phone:"0311112222">
如您所见,phone
值现在是一个以 0
开头的字符串。
您可以在 repl.it 上看到此代码的运行情况:https://repl.it/@jrunning/WellmadeFarflungCron
一边
为什么,你可能会问,这有点丑吗?
CSV::Converters[:float].call(
CSV::Converters[:integer].call(value))
这是因为 CSV 模块是这样定义 CSV::Converters 的:
Converters = {
integer: lambda { |f|
Integer(f.encode(ConverterEncoding)) rescue f
},
float: lambda { |f|
Float(f.encode(ConverterEncoding)) rescue f
},
numeric: [:integer, :float],
# ...
}
由于 :numeric
转换器未指定为 lambda,而是一个数组,表明它实际上只是 :integer
和 :float
转换器,我们不能只做 CSV::Converters[:numeric].call(value)
;我们必须手动调用这两个转换器。 (如果有人知道我遗漏了什么,请发表评论。)
关于ruby-on-rails - 如果它在 ruby 中以零开头,我无法从 csv 文件中获取确切的数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52025841/