Obtaining specific .csv data (one data at a time)


K

Kamarulnizam Rahim

Im using the following code:

class Target <
Struct.new:)question)
#Struct.new:)action, :blank, :cost, :status, :due_date,
:responsibility)
def print_csv_record
# use the ternary operator to use one output format or the other
question.length==0 ? printf(",") : printf("\"%s\",", question)
printf("\n")
end
end

CSV.open('ActionPlan.csv','rb').each do |row|
t = Target.new
t.question = row[1] if row[0].to_s.match(/1.[a-z]/)#maybe can use
each.line
pp t.question #<---to test outputs
end

The outputs are as followed:

nil
nil
nil
"Maximise use of natural lighting"
"Turn-off unnecessary lights/equipment"
"Install energy efficient lighting"
"Turn-off unnecessary air conditioning"
"Repair or replace damaged oven/refrigerator seals"
"Install draught proofing"
"Consider energy efficiency labels when buying electrical items"
"Insulate hot water pipes"
......
......

For some reason, ruby returns the entire line of row[1]. If i only
require one result at a time (i.e only "Turn-off unnecessary
lights/equipment") and do not want ruby to return any 'nil' output, how
can i tell ruby to do so?

Attached is the .csv file use. Thanks for any help

Nizam

Attachments:
http://www.ruby-forum.com/attachment/5806/ActionPlan.csv
 
Ad

Advertisements

J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

Im using the following code:

class Target <
Struct.new:)question)
#Struct.new:)action, :blank, :cost, :status, :due_date,
:responsibility)
def print_csv_record
# use the ternary operator to use one output format or the other
question.length==0 ? printf(",") : printf("\"%s\",", question)
printf("\n")
end
end
This bit here is a little cumbersome, it could probably be cleaned up like
this:

class Target < Struct.new:)question)
def print_csv_record
print %("#{question}") if question && !question.length.zero?
puts ","
end
end

Though, I think a better way to do this would be to return the string, and
let the calling code decide how it should be dealt with (ie sent to $stdout,
like puts does, or maybe saved to a file instead, or manipulated further,
elsewhere)

CSV.open('ActionPlan.csv','rb').each do |row|
t = Target.new
t.question = row[1] if row[0].to_s.match(/1.[a-z]/)#maybe can use
each.line
pp t.question #<---to test outputs
end
Here, you open the file, then iterate over it, but never close it. To
iterate over its rows, try using foreach instead, which handles the file
upkeep for you.

Also, you see the nils, because you create a target on every iteration,
regardless of whether you assign it a question. So if you create the target,
and it does not match the regex, then it will not have a question. So when
you say 'pp t.question', t.question will be nil, so that is the same as 'pp
nil', and you will see nil. It isn't clear to me what you were actually
wanting to happen, so here are two possibilities.


1, Assumes you meant to use print_csv_record, which will just output a comma
for empty records
CSV.foreach('ActionPlan.csv') do |row|
t = Target.new
t.question = row[1] if row[0] =~ /1.[a-z]/
t.print_csv_record
end

2. Assumes you wanted to skip output for rows that don't match your regex
CSV.foreach('ActionPlan.csv') do |row|
next unless row[0] =~ /1.[a-z]/
t = Target.new row[1]
t.print_csv_record
end
 
K

Kamarulnizam Rahim

Hi Josh,

Thanks for the post. Problem solved. But i have one little question to
ask. In order to get the data from row[1], i use the following code:

next unless row[0] =~ /1.[a-z]/
t = Target.new row[1]

where '1.[a-z]' will take on any data with number '1'. The problem is,
my csv data on row[1] has data till number '11'. and when i used the
code above, it will take on data on number '1' and '11' as well. How do
i separate this?

Nizam
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

Hi Josh,

Thanks for the post. Problem solved. But i have one little question to
ask. In order to get the data from row[1], i use the following code:

next unless row[0] =~ /1.[a-z]/
t = Target.new row[1]

where '1.[a-z]' will take on any data with number '1'. The problem is,
my csv data on row[1] has data till number '11'. and when i used the
code above, it will take on data on number '1' and '11' as well. How do
i separate this?

Nizam
In regular expressions, the period will match any character. So you need to
escape the period to basically say "match a period" not "match any
character"
/1\.[a-z]/
 
Ad

Advertisements

K

Kamarulnizam Rahim

Hi, I mistakenly look over my output.

I tried using the method above (/1\.[a-z]/)and it still give me the same
result which means it still take on data numbered '11'. Any idea to
solve this?

Nizam
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top