Naming a variable dynamically in Ruby [duplicate] - ruby

This question already has answers here:
How to dynamically create a local variable?
(4 answers)
Closed 7 years ago.
I am trying to perform the following operation.
#i, price_0, price_1, price_2 = 0, 0, 0, 0
until #i > 2 do
if trade_history[#i]["type"] == 2
price_"#{#i}" = (trade_history[#i]["xbt_gbp"]).to_f ##NOT WORKING
end
#i += 1;
end
I cannot find anywhere online where it says that you can dynamically name a variable in Ruby. What I want to be able to do is to extract the prices of the trade_history object whenever they have a type 2. I need to be able to use the prices variables (price_0..2) to make calculations at the end of the loop. Please help! :-)

Just store the values in an array:
prices = []
3.times do |i|
history = trade_history[i]
prices << history["xbt_gbp"].to_f if history["type"] == 2
end
After this loop the prices array would hold the results and look like this:
prices
#=> e.q. [0.2, 0.4, 0.5]
Calculations can be easily done with reduce or inject:
prices.inject(:+)
#=> 1.1

I do not think this is the best way to do it, you should rather use a Hash containing the prices, but if you really want to dynamically assign the local variables you created, use binding.local_variable_set.
binding.local_variable_set("price_#{#i}", "your value")
Note that this is only available from Ruby 2.1. See How to dynamically create a local variable? for more info.
If you prefer an instance variable, you can use.
instance_variable_set("#price_#{#i}", 1)

Related

ruby 'best way' to generate 2d array [duplicate]

This question already has answers here:
How to declare an empty 2-dimensional array in Ruby?
(5 answers)
Closed 6 years ago.
I have create empty array of array like below , Is there any other best way to initialize it ?.
arr = [[],[],[],[],[],[],[],[],[]]
I think the best way to achieve it by using Array class.
ex:
Array.new(width){Array.new(height)}
you can also provide width & height value like width = 2 & height = 4
Have you tried something like
arr = Array.new(9) { Array.new }
?

Ruby: evaluate string with dynamic binding of variables

I have a database of "formulas" stored as strings. Let's assume for simplicity, that each formula contains 2 variables denoted by a and b, and that the formulas are all wellformed and it is ensured that it consists only of characters from the set ()ab+-*.
At runtime, formulas are fetched from this database, and from another source, numeric values for a and b are fetched, and the formulas are evaluated. The evaluation can be programmed like this:
# This is how it works right now
formula = fetch_formula(....)
a = fetch_left_arg(....)
b = fetch_right_arg(....)
result = eval(formula)
This design works, but I'm not entirely happy with it. It requires that my program names the free variables exactly the same as they are named in the formula, which is ugly.
If my "formula" would not be a string, but a Proc object or Lambda which accepts two parameters, I could do something like
# No explicitly named variables
result = fetch_proc(...).call(fetch_left_arg(....),fetch_right_arg(....))
but unfortunately, the formulas have to be strings.
I tried to experiment in the following way: What if the method, which fetches the formula from the database, would wrap the string into something, which behaves like a block, and where I could pass parameters to it?
# This does not work of course, but maybe you get the idea:
block_string = "|a,b| #{fetch_formula(....)}"
Of course I can't eval such a block_string, but is there something similar which I could use? I know that instance_eval can pass parameters, but what object should I apply it to? So this is perhaps not an option either....
This is very nasty approach, but for simple formulas you’ve mentioned it should work:
▶ formula = 'a + b'
▶ vars = formula.scan(/[a-z]+/).uniq.join(',') # getting vars names
#⇒ "a,b"
▶ pr = eval("proc { |#{vars}| #{formula} }") # preparing proc
▶ pr.call 3, 5
#⇒ 8
Here we rely on the fact, that parameters are passed to the proc in the same order, as they appear in the formula.
If I get your question correctly, it is something that I have done recently, and is fairly easy. Given a string:
s = "{|x, y| x + y}"
You can create a proc by doing:
eval("Proc.new#{s}")
One way to avoid creating the variables in the local scope could be to use a Binding:
bind = binding
formula = fetch_formula(....)
bind.local_variable_set :a, fetch_left_arg(....)
bind.local_variable_set :b, fetch_right_arg(....)
result = bind.eval(formula)
The variables a and b now only exist in the binding, and do not pollute the rest of your code.
You can create a lambda from string, as shown below:
formula = "a + b"
lambda_template = "->(a,b) { %s }"
formula_lambda = eval(lambda_template % formula)
p formula_lambda.call(1,2)
#=> 3

Ruby // Random number between range, ensure uniqueness against others existing stored ones

Currently trying to generate a random number in a specific range;
and ensure that it would be unique against others stored records.
Using Mysql. Could be like an id, incremented; but can't be it.
Currently testing other existing records in an 'expensive' manner;
but I'm pretty sure that there would be a clean 1/2 lines of code to use
Currently using :
test = 0
Order.all.each do |ord|
test = (0..899999).to_a.sample.to_s.rjust(6, '0')
if Order.find_by_number(test).nil? then
break
end
end
return test
Thanks for any help
Here your are my one-line solution. It is also the quicker one since calls .pluck to retrieve the numbers from the Order table. .select instantiates an "Order" object for every record (that is very costly and unnecessary) while .pluck does not. It also avoids to iterate again each object with a .map to get the "number" field. We can avoid the second .map as well if we convert, using CAST in this case, to a numeric value from the database.
(Array(0...899999) - Order.pluck("CAST('number' AS UNSIGNED)")).sample.to_s.rjust(6, '0')
I would do something like this:
# gets all existing IDs
existing_ids = Order.all.select(:number).map(&:number).map(&:to_i)
# removes them from the acceptable range
available_numbers = (0..899999).to_a - existing_ids
# choose one (which is not in the DB)
available_numbers.sample.to_s.rjust(6, '0')
I think, you can do something like below :
def uniq_num_add(arr)
loop do
rndm = rand(1..15) # I took this range as an example
# random number will be added to the array, when the number will
# not be present
break arr<< "%02d" % rndm unless arr.include?(rndm)
end
end
array = []
3.times do
uniq_num_add(array)
end
array # => ["02", "15", "04"]

How do I create an object that will have a number at the end that will increment each time it is used?

I am trying to make a variable that I can increment each time after I use it.
The $companyLevel os the variable that I need to increment.
count = 20
# Variables (20)
while count > 0
$levelName = ""; 8.times{$levelName << (65 + rand(25)).chr}
$companyLevel = "CLev5"
browser2.button(:id, "addCompanyLevel").click
sleep 2
browser2.text_field(:id, $companyLevel).set $levelName
$companyLevel += 1
count -= 1
end
How do I create a variable that will have a number at the end that will increment each time it is used?
Thanks.
Since you already have a count, why does this need to be a variable? why not just do simple string concatenation to create the value you want on the fly
companyLevel = "CLev" + count.to_s
Unless you need to perhaps read up on what an 'array' is?
I'd suggest you purchase and read the book "Everyday Scripting with Ruby" it's a great way to lean the basics of the ruby language and geared towards testers.
This is achieved by creating an object with a property that increments not by creating a variable that increments.

Change variable passed in a method [duplicate]

This question already has answers here:
'pass parameter by reference' in Ruby?
(6 answers)
Closed 8 years ago.
How can I change the contents of a variable using a method? Maybe I'm not saying this correctly. What is a way to get the reference to a variable like in C? Example:
// main stuff
int gorilla = 29;
makeMeABanana(&gorilla);
void makeMeABanana(int *gorilla) { }
How can I do something like this in Ruby?
You should not do this - you're just porting techniques that are fully appropriate to C to Ruby, where they are no longer appropriate. There are several fancy ways around this (eg using a Proc closed over your calling namespace, or eval) but they are usually inappropriate in Ruby unless you know precisely what you're doing.
Recently on the ruby-talk mailing list, someone asked about writing a swap function where swap(a,b) would swap the values of the variables "a" and "b". Normally this cannot be done in Ruby because the swap function would have no reference to the binding of the calling function.
However, if we explictly pass in the binding, then it is possible to write a swap-like function. Here is a simple attempt:
def swap(var_a, var_b, vars)
old_a = eval var_a, vars
old_b = eval var_b, vars
eval "#{var_a} = #{old_b}", vars
eval "#{var_b} = #{old_a}", vars
end
a = 22
b = 33
swap ("a", "b", binding)
p a # => 33
p b # => 22
This actually works! But it has one big drawback. The old values of "a" and "b" are interpolated into a string. As long as the old values are simple literals (e.g. integers or strings), then the last two eval statements will look like: eval "a = 33", vars". But if the old values are complex objects, then the eval would look like eval "a = #", vars. Oops, this will fail for any value that can not survive a round trip to a string and back.
Referred from : http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc
Integers are objects, with an id, like everything else in Ruby. They are implemented like this:
p (0..10).map{|n| n.object_id}
#=>[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
All other objects have even object_id numbers. There is no way to change 7 (object_id 15) into something else.

Resources