Accessing an array of vectors trouble - ruby

My code looks like this:
a = IO.readlines("input.txt").map { |line| Vector.[](line.split) }
Now I want to access a single component of the first vector within my a array. I'm writing the following to address a vector:
puts a[0]
The behavior is pretty much expected - I receive the following:
Vector[1.2357, 2.1742, -5.4834, -2.0735]
Now let's try to address a single component this way:
puts a[0][0]
and voila, I receive a list of all the vector components,like:
1.2357
2.1742
-5.4834
-2.0735
How come? Maybe the last attempt was wrong? How do I correctly address a scalar inside a vector within an array?

Due to your code I think the array construction should be:
a = IO.readlines("input.txt").map { |line| Vector[*line.split] }

Related

How to add object attributes in array from another array in Ruby

Firstly I have an array of multiple objects [#<Vgpop::Game:0x00007fcd5b246a00 #name="Super Smash Bros. Ultimate", #console=nil, #score=nil>....]
Then I have an array of my consoles that looks like this: ["Nintendo Switch"...]
How do I map the values from my second array to my object array so that the return is:
[#<Vgpop::Game:0x00007fcd5b246a00 #name="Super Smash Bros. Ultimate", #console="Nintendo Switch", #score=nil>....]
Seems like we can come up with this solution my friend:
first_array.each_with_index { |vgpop, i| vgpop.name = second_array[i] }

Access variable hash depth values with square brackets notation

Given this hash:
hash1= { node1: { node2: { node3: { node4: { node5: 1 } } } } }
We access inside nodes with square brackets like this:
hash1[:node1][:node2][:node3][:node4]
Now I have a hash that I know will always be nested as it is an XML response from a SOAP webservice, but neither the depth of the hash nor the names of the nodes stay the same. So it would be nice if I could ask the user of my application for the hash depth and store it in a variable. And then be able to do hash1[:hash_depth] and achieve the same result as above.
I have accomplished what I want by the following code:
str = 'node1,node2,node3,node4'
str_a = str.split(',')
hash_copy = hash1
str_a.each { |s| hash_copy = hash_copy.[](s.to_sym) }
hash_copy
=> {:node5=>1}
hash1[:node1][:node2][:node3][:node4]
=> {:node5=>1}
that is asking the user to enter the hash depth separated by commas, store it in a string, split it, make an array, clone the original hash, go down each level and modify the hash till I get to the desired node. Is there a way to do it with the square brackets notation and using a variable to store the depth without modifying the hash or needing to clone it?
Edit:
someone answered with the following (can't see his post anymore???)
hash_depth="[:node1][:node2][:node3][:node4]"
eval "hash1#{hash_depth}"
Although eval does everything you need, there is another approach, since you already have the working code for comma-separated list:
hash_depth="[:node1][:node2][:node3][:node4]"
csh = hash_depth.gsub(/\A\[:|\]\[:|\]\Z/, { '][:' => ',' })
#⇒ "node1,node2,node3,node4"
And now you are free to apply your existing function to csh.
If this is a webapp, I think you should prepare a list of short textareas, which starts with a single text item, and the user can keep adding a new item to the list by clicking on a button. The areas will be filled by the user, and will be sent.
Then, you will probably receive this through some serialized form. You decode this to get an array of strings:
str_a = ["node1", "node2", "node3", "node4"]
and you can reach the inner element by doing:
str_a.inject(hash1){|h, s| h[s.to_sym]} #=> {:node5 => 1}

How to go through a loop and create a new object with each iteration Ruby?

I saw several variations of this question but did not really find a solid answer.
So I have an array of URLS. I want to loop through that array and for each individual URL, I would create an instance of class WebPages.
So if array URLS has 5 urls in it, then I would create 5 objects of WebPages. I tried to use eval() to do this but quickly learned that the instances made by eval have a very local scope and I cannot use those WebPage objects after.
string_to_eval = #urls.map{|x| "webpage#{urls.index(x)} = WebPage.new('# {x}')"}.join(';')
puts string_to_eval
eval(string_to_eval)
String_to_eval prints out:
webpage0 = WebPage.new('http://www.google.com');
webpage1 = WebPage.new('http://www.yahoo.com');
webpage2 = WebPage.new('http://www.amazon.com');
webpage3 = WebPage.new('http://www.ebay.com')
How else can I make an object with each iteration of the loop in Ruby? Is there a way around this?
Why not just this?
webpages = #urls.map { |url| WebPage.new(url) }
It is generally a bad idea to have webpage0, webpage1... when you can have webpages[0], webpages[1]... (Also, the array way does not require the Evil of eval.)
In this situation I would forgo unique variable names and instead simply leave the resulting objects in an array. In that case the code would look like this:
>> #urls.map{|url| WebPage.new(url)}
=> [WebPage('http://www.google.com'), WebPage('http://www.yahoo.com'), WebPage('http://www.amazon.com'), WebPage('http://www.ebay.com') ]

ruby - calling a method on a dynamically named object

I have an array of strings, that represent existing object names.
JoesDev = Dev.new
MarksDev = Dev.new
SamsDev = Dev.new
devices=['JoesDev', 'MarksDev', 'SamsDev' ]
i'd like to iterate over the devices array, while calling a method on the objects that each item in the array is named after.
i.e;
JoesDev.method_name
MarksDev.method_name
SamsDev.method_name
how can i do this? thx.
devices.each{|name| self.class.const_get(name).method_name}
You can use the const_get method from Module to have Ruby return the constant with the given name. In your case, it will return the Dev instance for whatever device name you give it.
Using .each to iterate the items, your code could look like
devices.each do |device_name|
device = self.class.const_get(device_name)
device.method_name
end
# Which can be shortened to
devices.each{ |dev| self.class.const_get(dev).method_name }
However, there are better ways to implement this type of thing. The most common way is using a Hash. In your example, the list of devices could look something like
devices = {
joe: Dev.new,
mark: Dev.new,
sam: Dev.new
}
Then, iterating over the devices is as simple as
devices.each do |dev|
dev.method_name
end
# Or
devices.each{ |dev| dev.method_name }
Extra: If you want to get a little fancy, you can use the block version of Hash::new to make adding new devices extremely simple.
# Create the hash
devices = Hash.new{ |hash, key| hash[key] = Dev.new }
# Add the devices
devices['joe']
devices['mark']
devices['sam']
This kind of hash works exactly the same as the one shown above, but will create a new entry if the given key cannot be found in the hash. A potential problem with this design, then, is that you can accidentally add new devices if you make a typo. For example
devices['jon'] # This would make a new Dev instance, which may be undesirable.
Well one way is surely to use eval, a method that allows you to execute arbitrary strings as if they were code.
So, in your example:
var_names.each{ |var_name| eval("#{var_name}.some_method") }
Needless to say, it is very dangerous to let unfiltered strings to be used as code, very bad things™ may happen!

does ruby have an elegant way to say array2 = some_lookup_method(array1)

I have an array short_code[] that contains an array of short product identifiers such as ["11111", "2222", "33333"]
I want to create a copy of the array that contains the corresponding 'long code' data:
long_code[i] = my_lookup_long_code(short_code[i])
While simple iteration is easy, I'm wondering, as a relative ruby newbie, what is the 'ruby way' to create an array which is a simply method() applied on every element in the original array?
You can use the map command, which will return a new array with the results of your code block:
long_code = short_code.map{ |code| my_lookup_long_code(code) }

Resources