Confusion with CSV::filter output

Code :

require ‘csv’

content = <<CSV
id,first name,last name,age,sex
12,arup,rakshit,26,M
11,ayan,das,25,M
44,puja,roy,19,F
18,Dolly,Sen,21,F
CSV

File.write(‘a.csv’,content)

CSV.foreach(‘a.csv’) do |row|
p row
end

output

>> [“id”, “first name”, “last name”, “age”, “sex”]

>> [“12”, “arup”, “rakshit”, “26”, “M”]

>> [“11”, “ayan”, “das”, “25”, “M”]

>> [“44”, “puja”, “roy”, “19”, “F”]

>> [“18”, “Dolly”, “Sen”, “21”, “F”]

Till now perfect. But why the same is not happening with CSV::filter
(Class: CSV (Ruby 2.1.0))
method. I am not getting the rows, rather than name of the file twice.
What wrong I did ?

CSV.filter(‘a.csv’,:col_sep => “,”) do |csv|
p csv
end

>> [“a.csv”]

>> a.csv

I fixed my code :

require ‘csv’

content = <<CSV
id,first name,last name,age,sex
12,arup,rakshit,26,M
11,ayan,das,25,M
44,puja,roy,19,F
18,Dolly,Sen,21,F
CSV

File.write(‘a.csv’,content)

#CSV.foreach(‘a.csv’) do |row|

p row

#end

input = File.new(‘a.csv’,‘r’)
output = File.new(‘b.csv’,‘w’)

CSV.filter(input,output,:col_sep => “,”,:headers => true) do |csv|
csv[‘status’] = “eligible” if csv[‘sex’] == “F”
end
output.close

CSV.foreach(‘b.csv’) do |row|
p row
end

>> [“12”, “arup”, “rakshit”, “26”, “M”]

>> [“11”, “ayan”, “das”, “25”, “M”]

>> [“44”, “puja”, “roy”, “19”, “F”, “eligible”]

>> [“18”, “Dolly”, “Sen”, “21”, “F”, “eligible”]

Question : why [‘id’,‘first name’,‘last name’,‘age’,‘sex’] is missing
from the output and how to add it ?

Try…

CSV.filter(input,output,:col_sep => “,”,:headers => true,
:return_headers => true) do |csv|

Abinoam Jr.

Abinoam Jr. wrote in post #1136756:

Try…

CSV.filter(input,output,:col_sep => “,”,:headers => true,
:return_headers => true) do |csv|

Tried and worked… Thanks as always.

require ‘csv’

content = <<CSV
id,first name,last name,age,sex
12,arup,rakshit,26,M
11,ayan,das,25,M
44,puja,roy,19,F
18,Dolly,Sen,21,F
CSV

File.write(‘a.csv’,content)

#CSV.foreach(‘a.csv’) do |row|

p row

#end

input = File.new(‘a.csv’,‘r’)
output = File.new(‘b.csv’,‘w’)

CSV.filter(input,output,:col_sep => “,”,:headers => true,:return_headers
=> true) do |csv|
next csv[‘status’] = “eligible” if csv[‘sex’] == “F”
csv[‘status’] = “”
end
output.close

CSV.foreach(‘b.csv’) do |row|
p row
end

>> [“id”, “first name”, “last name”, “age”, “sex”, “”]

>> [“12”, “arup”, “rakshit”, “26”, “M”, “”]

>> [“11”, “ayan”, “das”, “25”, “M”, “”]

>> [“44”, “puja”, “roy”, “19”, “F”, “eligible”]

>> [“18”, “Dolly”, “Sen”, “21”, “F”, “eligible”]

Now you can see, I have added one more column “status”, inside the
block, can this be added to the header row, and get the output as -

[“id”, “first name”, “last name”, “age”, “sex”, “status”] ?

CSV.filter(input,output,:col_sep => “,”,:headers => true,
:return_headers => true) do |csv|
csv << ‘status’ if csv.header_row?
csv[‘status’] = “eligible” if csv[‘sex’] == “F”
end

But I bet there’s a more elegant (and optimized) way to do it.
I think you should add the row “before” the filter, so you’ll do it
once, and not test it each line.

Abinoam Jr.

Abinoam Jr. wrote in post #1136762:

CSV.filter(input,output,:col_sep => “,”,:headers => true,
:return_headers => true) do |csv|
csv << ‘status’ if csv.header_row?
csv[‘status’] = “eligible” if csv[‘sex’] == “F”
end

Yes, it is done! Thank you very much!