Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Representing a variable with your own code 3

Status
Not open for further replies.

Trevoke

Programmer
Jun 6, 2002
1,142
US
I'm going to be iterating through a set of data and, depending on a filter, it may go into one variable or another (only two variables to be considered for this example). Each variable represents an HTML table.

I could do a big if-else, or iterate through the data twice, but I hate repeating code.
Is there a way to have the program say "If X, then use this variable for the remainder of this loop, and if !X, then use THIS variable" ?

Tao Te Ching Discussions : Chapter 9 (includes links to previous chapters)
What is the nature of conflict?
 
Hi Trevoke,
I'm not sure if I understand you good. It would be great, if you can give us an example.
but I hate repeating code
then use functions/procedures/methods
Is there a way to have the program say "If X, then use this variable for the remainder of this loop, and if !X, then use THIS variable" ?
If your remainder_of_loop is implemented as a function/procedure depending of an input parameter, e.g. remainder_of_loop(parameter), you can simply call it wit an input you need:
Code:
if X
  remainder_of_loop(X)
end
...
if !X 
  remainder_of_loop(THIS)
end
 
Well, here's what's happening:

Code:
array.each do |i|
  if i[0] == 'foo'
    bar = "One more for the road!"
  else
    baz = "One more for the road!"
  end
end

Except there is much more than just one assignment to the same variable, so I end up adding four or five things to 'bar' OR 'baz' depending on what i[0] is.

Tao Te Ching Discussions : Chapter 9 (includes links to previous chapters)
What is the nature of conflict?
 
One way could be to store the contents of the all asigned variables in a hash and the name of an actual variable in another variable.
Then after leaving the decision block you have the hash of all variables you assigned and the name of last variable, so you can process it further:
Code:
array = [[COLOR=#6a5acd]'[/color][COLOR=#ff00ff]foo[/color][COLOR=#6a5acd]'[/color], [COLOR=#6a5acd]'[/color][COLOR=#ff00ff]val1[/color][COLOR=#6a5acd]'[/color], [COLOR=#6a5acd]'[/color][COLOR=#ff00ff]val2[/color][COLOR=#6a5acd]'[/color]]
puts array.inspect

vars_hash = [COLOR=#2e8b57][b]Hash[/b][/color].new([COLOR=#ff00ff]:var_is_undefined[/color])
usevar =[COLOR=#6a5acd]""[/color]

array.each [COLOR=#804040][b]do[/b][/color] |[COLOR=#008080]i[/color]|
  [COLOR=#804040][b]if[/b][/color] i == [COLOR=#6a5acd]'[/color][COLOR=#ff00ff]foo[/color][COLOR=#6a5acd]'[/color]
    usevar = [COLOR=#6a5acd]'[/color][COLOR=#ff00ff]bar[/color][COLOR=#6a5acd]'[/color].to_sym  [COLOR=#0000ff]# convert to symbol[/color]
    vars_hash[usevar] = [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]One more for the road![/color][COLOR=#6a5acd]"[/color]
  [COLOR=#804040][b]else[/b][/color]
    usevar = [COLOR=#6a5acd]'[/color][COLOR=#ff00ff]baz[/color][COLOR=#6a5acd]'[/color].to_sym  [COLOR=#0000ff]# convert to symbol[/color]
    vars_hash[usevar] = [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]One more for the road![/color][COLOR=#6a5acd]"[/color]
  [COLOR=#804040][b]end[/b][/color]
[COLOR=#804040][b]end[/b][/color]
puts

[COLOR=#0000ff]# the variable usevar is symbol[/color]
puts [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]The variable '[/color][COLOR=#6a5acd]#{[/color]usevar[COLOR=#6a5acd]}[/color][COLOR=#ff00ff]' is a [/color][COLOR=#6a5acd]#{[/color]usevar.class[COLOR=#6a5acd]}[/color][COLOR=#ff00ff] named [/color][COLOR=#6a5acd]#{[/color]usevar.inspect[COLOR=#6a5acd]}[/color][COLOR=#6a5acd]"[/color]
puts

[COLOR=#0000ff]# the hash contains[/color]
puts [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]The hash contains:[/color][COLOR=#6a5acd]"[/color]
puts [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]vars_hash = [/color][COLOR=#6a5acd]#{[/color]vars_hash.inspect[COLOR=#6a5acd]}[/color][COLOR=#6a5acd]"[/color]
puts [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]vars_hash[:bar] = [/color][COLOR=#6a5acd]#{[/color]vars_hash[[COLOR=#ff00ff]:bar[/color]][COLOR=#6a5acd]}[/color][COLOR=#6a5acd]"[/color]
puts [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]vars_hash[:foo] = [/color][COLOR=#6a5acd]#{[/color]vars_hash[[COLOR=#ff00ff]:foo[/color]][COLOR=#6a5acd]}[/color][COLOR=#6a5acd]"[/color]
puts

[COLOR=#0000ff]# Now processing the variable/symbol which is stored in usevar[/color]
puts [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]Now processing the last used variable '[/color][COLOR=#6a5acd]#{[/color]usevar[COLOR=#6a5acd]}[/color][COLOR=#ff00ff]':[/color][COLOR=#6a5acd]"[/color]
puts [COLOR=#6a5acd]"[/color][COLOR=#ff00ff]The value of variable '[/color][COLOR=#6a5acd]#{[/color]usevar[COLOR=#6a5acd]}[/color][COLOR=#ff00ff]' is: '[/color][COLOR=#6a5acd]#{[/color]vars_hash[usevar][COLOR=#6a5acd]}[/color][COLOR=#ff00ff]'[/color][COLOR=#6a5acd]"[/color]
Output:
Code:
C:\Users\Roman\Work>ruby trevoke.rb
["foo", "val1", "val2"]

The variable 'baz' is a Symbol named :baz

The hash contains:
vars_hash = {:baz=>"One more for the road!", :bar=>"One more for the road!"}
vars_hash[:bar] = One more for the road!
vars_hash[:foo] = var_is_undefined

Now processing the last used variable 'baz':
The value of variable 'baz' is: 'One more for the road!'
 
Probably a bit late on this one, but here goes anyway...

When you have a requirement for a soft reference like this, it usually means your design is wrong. Mostly it's caused by people not using an array, and ending up with a set of variables like v1, v2 ... vn. In this instance it's a named variable, so mikrom's second solution using the hash is a good way around this (although I'm not sure we need to convert the keys into symbols). Even then, this pattern is normally used where you don't know in advance what the variables could be called (example: a generic CSV file reader with the column names in the first row of the file). But this doesn't appear to be the case, in which case mikrom's first suggestion would be better, with a couple of adjustments)
Ruby:
if a[0] == 'foo'
  bar = remainder_of_loop
else
  baz = remainder_of_loop
end

def remainder_of_loop
  # return some complex compound value here
end
So I'm back to questioning the design again - I get the feeling that if we thought a bit harder about the overall design, you wouldn't have this problem to solve...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Hi stevexff,

We don't need convert string keys into symbols, it would work with strings too.
But I have read that using symbols is more efficient than using strings and so I thought that it would be better to use symbols than strings for naming variables.
:)
 
Well, here's the actual code, since now I'm reworking it and adding more stuff. I made the changes such as mikrom suggested, and I do like it much better that way.

Still.. Now I get an error when I run it:

C:/scripts/ReportParsers/lib/CheckDictaForReports.rb:70:in `[]=': index 10449 out of string (IndexError)
from C:/scripts/ReportParsers/lib/CheckDictaForReports.rb:70
from C:/scripts/ReportParsers/lib/CheckDictaForReports.rb:34:in `each'
from C:/scripts/ReportParsers/lib/CheckDictaForReports.rb:34
That line number is when I start assigning HTML to modvar[:non_cr].
Any idea? I'm not sure why this fails...


Code:
#TODO create two html tables to separate CR from the rest.

require 'rubygems'
require 'activerecord' # gem install activerecord
# Activerecord is only required because of how easy it makes date manipulation.
require 'report' # should be in same folder
require 'timestamp' # should be in same folder
require 'pp' #pretty print, useful for debugging

# In Ruby, variables that begin with an upper-case letter are constants.
# This reminds the programmer not to mess with the content without good reason.
# Ruby is flexible and WILL let you change the value - so be responsible.
# Don't drink and derive.
Folders_FullPath = ['//pluto/transcript/radiology/dictamatic_preview',
                    '//pluto/transcript/radiology/teleradiology_preview/qa']
Monday = Date.today.monday
Timestamp = get_timestamp
#This mymod / modvar combo is used for basic Don't Repeat Yourself coding.
#Look for it when I iterate through the previews, around line 77.
mymod = {:cr => "", :non_cr => ""}
modvar = ""
myshade = {:shade_cr => false, :shade_non_cr => false}
shadevar = ""

file = %Q{<HTML>
<HEAD>
<TITLE>Dictamatic_Preview sorted by date, then last name</TITLE>
</HEAD>
<BODY>
Report generated on <b>#{Time.now}</b><br/>
Bolded lines mean a report has been in the folder more than 18 hours.<br/>
  }

Folders_FullPath.each do |folder|
  previews = []
  # go to folder
  Dir.chdir folder
  # get list of files - 'glob' is actually a filter, * means 'get everything'.
  Dir.glob('*') do |item|
    # We don't want directories or temp Word files.
    next if File.directory? item
    next if item[0..0] == "~"
    begin
      previews << (Report.new item)
    rescue
      puts "#{item}"
      puts "This thing made it crash."
      System.END 0
    end
  end


  #Sorting in ascending order.
  previews.sort! do |file1,file2|
    # Clever hack for dual sort - by date then last name.
    comp = file1.date <=> file2.date
    comp.zero? ? (file1.last <=> file2.last) : comp
  end

  total_exams_in_folder = previews.size
  exams_before_this_past_mon = 0
  # Getting total exams in Dictamatic_Preview from before Monday.
  previews.each { |i| exams_before_this_past_mon += 1 if i.date < Monday }
  folder_name = folder.split('/')[-1].upcase

  file << %Q{<b><center>EXAMS IN #{folder_name}: #{total_exams_in_folder}<br/>
Exams from before #{Monday}: #{exams_before_this_past_mon}</center></b><br/>
  }

  modvar[:non_cr] = %Q{<b><center>MODALITIES OTHER THAN CR</center></b>
<table>\n<tr><th>Name</th><th>Date</th><th>Age</th><th>Procedure</th></tr>\n}
  modvar[:cr] = %Q{<b><center>CR ONLY</center></b>
<table>\n<tr><th>Name</th><th>Date</th><th>Age</th><th>Procedure</th></tr>\n}


  previews.each do |i|
    bold = i.age[0..1].to_i > 18 and i.age[-2..-1] == "hr"
    # The famous ternary operator. I set usevar to :cr or :non_cr.
    modvar = i.modality == 'CR' ? 'cr'.to_sym : 'non_cr'.to_sym
    shadevar = modvar == 'cr'.to_sym ? 'shade_cr'.to_sym : 'shade_non_cr'.to_sym
    #Maybe I'm taking it a little far.
    #This is borderline unreadable. If modvar is :cr, then I set the shadevar
    #to one thing, otherwise I set it to another thing.
    name = "#{i.last}, #{i.first}"
    mymod[modvar] << (myshade[shadevar] ? "<tr bgcolor=#DDDDDD>" : "<tr>")
    # Don't you just love the ternary operator? Way to condense code!
    myshade[shadevar] = !myshade[shadevar]

    mymod[modvar] << bold ? "<td><b>#{name}</b></td>" : "<td>#{name}</td>"
    mymod[modvar] << bold ? "<td><b>#{i.date}</b></td>" : "<td>#{i.date}</td>"
    mymod[modvar] << bold ? "<td><b>#{i.age}</b></td>" : "<td>#{i.age}</td>"
    mymod[modvar] << bold ? "<td><b>#{i.proc}</b></td>" : "<td>#{i.proc}</td>"
    mymod[modvar] << "</tr>\n"
  end
  mymod[modvar] << "</table>"
  mymod.each_value { |v| file << v << "\n" }
end

file << %Q{
</BODY>
</HTML>}

# I am opening a file and using it as the object of a block of code.
# The file is closed automatically when the block ends.
File.open("c:/reports/Dictamatic_Preview/#{Timestamp}.html", 'w') do |f|
  f << file
end

Tao Te Ching Discussions : Chapter 9 (includes links to previous chapters)
What is the nature of conflict?
 
Hi

To me seems that you mixed up modvar and mymod there :
Code:
  [highlight]mymod[/highlight][teal][:[/teal]non_cr[teal]][/teal] [teal]=[/teal] [teal]%[/teal]Q[teal]{[/teal][green][i]<b><center>[/i][/green]MODALITIES OTHER THAN CR[green][i]</center></b>[/i][/green]
[green][i]<table>[/i][/green][teal]\[/teal]n[green][i]<tr><th>[/i][/green]Name[green][i]</th><th>[/i][/green]Date[green][i]</th><th>[/i][/green]Age[green][i]</th><th>[/i][/green]Procedure[green][i]</th></tr>[/i][/green][teal]\[/teal]n[teal]}[/teal]
  [highlight]mymod[/highlight][teal][:[/teal]cr[teal]][/teal] [teal]=[/teal] [teal]%[/teal]Q[teal]{[/teal][green][i]<b><center>[/i][/green]CR ONLY[green][i]</center></b>[/i][/green]
[green][i]<table>[/i][/green][teal]\[/teal]n[green][i]<tr><th>[/i][/green]Name[green][i]</th><th>[/i][/green]Date[green][i]</th><th>[/i][/green]Age[green][i]</th><th>[/i][/green]Procedure[green][i]</th></tr>[/i][/green][teal]\[/teal]n[teal]}[/teal]

Feherke.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top