I tried to pass array of string to use puts in ruby print it value with math operator. But get the wrong result. I thingk it need to convert to object to achieve this as follow.
my_string_array = ["100*(4+1)"]
my_string = my_string_array.join(' ') # => "100*(4+1)"
my_ruby_valuation = my_string.to_i # => 100 (Wrong)
What I expected is
puts my_ruby_valuation #=> 500
You should use eval kernel function.
https://apidock.com/ruby/Kernel/eval
my_string_array = ["100*(4+1)"]
eval(my_string_array[0])
I hope this helps.
Related
I have the following hash string:
arr = ["{:id=>1, :name=>\"a\"}", "{:id=>2, :name=>\"b\"}"]
How can I parse the data and get all id keys in a array like this: [1,2]
Thanks.
Since this array of strings doesn't seem to be exactly valid JSON, you can parse out the ids by doing something like the following:
arr = ["{:id=>1, :name=>\"a\"}", "{:id=>2, :name=>\"b\"}"]
arr.map { |x| x.split(":id=>").last.split(",").first.to_i }
# => [1, 2]
Hope this helps!
Looks like Ruby hashes which need to be evaluated, so use eval within a map:
arr.map{|hash| eval(hash)[:id]}
This is an array of JSON strings. You can use JSON.parse to parse them
arr = ["{:id=>1, :name=>\"a\"}", "{:id=>2, :name=>\"b\"}"]
ids = arr.map do |raw| # iterate on each string
JSON.parse(raw)[:id] # parse and extract the id
end
puts ids # => [1,2]
I have an object that I want to output a bunch of methods' results from. I have an array of method names and want to iterate through them:
img = Magick::Image::read('/Users/rich/Projects/imagemagick/orig/IMG_4677.jpg')[0]
atts = "background_color base_columns base_filename base_rows bias black_point_compensation".split(' ')
atts.each do |i|
puts img.i # problem evaluating i
end
I have tried string interpolation and eval but I can't get it to realize it's a method call.
Is there a way I can apply an array as method names to an object?
Try using public_send:
atts = "upcase downcase".split
atts.each do |i|
puts 'hEllO'.public_send(i)
end
#HELLO
#hello
How can I convert an array of arrays to a hash?
arr = [['me',1],['he',2],['she',3]]
I want to have
{'me':1,'he':2,'she':3}
my current solutions is
hsh={}
arr.each do |x| p hsh[x[0]] = x[1] end
hsh # => {'me':1,'he':2,'she':3}
but it looks ugly. My code works, but I am looking for a more convenient way to do it.
Try the to_h method
arr = [['me',1],['he',2],['she',3]]
arr.to_h
# => {'me' => 1, 'he' => 2, 'she' => 3}
Note that this won't turn the original strings into symbols. I'm not sure if that is part of your question. If so, you'll have to go with Sawa's solution.
arr.map{|k, v| [k.to_sym, v]}.to_h
First of all I think your array should be either this:
arr = [['me',1],[['he',2],['she',3]]]
OR
arr = [['me',1],['he',2],['she',3]]
There is some issue in number of '[' and ']'
One solution that will work for both is as follows:
hsh = Hash[*arr.flatten]
I have a Ruby array (don't ask me why it is not hash already, i can't do anything about it):
[{":cost=>100", ":size=>2"}]
What do i need to do to make it the classical Ruby hash with keys and values?
What is my best option? Maybe there is some libraries for this kind of operations?
Thanks.
First we need to clean the string to make it look like a valid array:
my_string = my_string[2..-3]
my_array = eval("[#{my_string}]")
Now you can join the strings, and then eval it into a hash:
elements = my_array.join(', ')
my_hash = eval("{ #{ elements } }")
(this can be done in fewer lines, but I separated them for clarity)
You could use the JSON module to do that. That would arguably be safer than by using eval.
To see how JSON could be used, let's do some reverse-engineering. You want to create a hash:
h = { :cost=>100, :size=>2 }
from the string:
str = '[{":cost=>100", ":size=>2"}]'
#=> "[{\":cost=>100\", \":size=>2\"}]"
Let's see how that hash would be encoded as a JSON string:
require 'json'
jstr = JSON.generate(h)
#=> "{\"cost\":100,\"size\":2}"
Once we have jstr (which is nothing more than a string) we can extract the desired hash:
JSON.parse(jstr)
#=> {"cost"=>100, "size"=>2}
so the task reduces to converting str to jstr:
"[{\":cost=>100\", \":size=>2\"}]" => "{\"cost\":100,\"size\":2}"
Perhaps the easiest way is to first pull out the keys and values, which we can do with a regex:
r = /
( # start capture group 1
[a-z] # match a lowercase letter
\w* # match >= 0 word characters
) # close capture group 1
=> # match characters
(-?\d+) # optionally match a minus sign followed by > 0 digits in
# capture group 2
/x # free-spacing regex definition mode
arr = str.scan r
#=> [["cost", "100"], ["size", "2"]]
We can now form jstr:
jstr = "{#{ arr.map { |k,v| "\"#{k}\":#{v}" }.join(",") }}"
#=> "{\"cost\":100,\"size\":2}"
To confirm,
h = JSON.parse(jstr)
#=> {"cost"=>100, "size"=>2}
Perhaps I have made this more complicated than I need it to be but I am currently trying to store an array that contains, among other things, an array inside a hash in Perl.
i.e. hash -> array -> array
use strict;
my %DEVICE_INFORMATION = {}; #global hash
sub someFunction() {
my $key = 'name';
my #storage = ();
#assume file was properly opened here for the foreach-loop
foreach my $line (<DATA>) {
if(conditional) {
my #ports = ();
$storage[0] = 'banana';
$storage[1] = \#ports;
$storage[2] = '0';
$DEVICE_INFORMATION{$key} = \#storage;
}
elsif(conditional) {
push #{$DEVICE_INFORMATION{$key}[1]}, 5;
}
}#end foreach
} #end someFunction
This is a simplified version of the code I am writing. I have a subroutine that I call in the main. It parses a very specifically designed file. That file guarantees that the if statement fires before subsequent elsif statement.
I think the push call in the elsif statement is not working properly - i.e. 5 is not being stored in the #ports array that should exist in the #storage array that should be returned when I hash the key into DEVICE_INFORMATION.
In the main I try and print out each element of the #storage array to check that things are running smoothly.
#main execution
&someFunction();
print $DEVICE_INFORMATION{'name'}[0];
print $DEVICE_INFORMATION{'name'}[1];
print $DEVICE_INFORMATION{'name'}[2];
The output for this ends up being... banana ARRAY(blahblah) 0
If I change the print statement for the middle call to:
print #{$DEVICE_INFORMATION{'name'}[1]};
Or to:
print #{$DEVICE_INFORMATION{'name'}[1]}[0];
The output changes to banana [blankspace] 0
Please advise on how I can properly update the #ports array while it is stored inside the #storage array that has been hash'd into DEVICE_INFORMATION and then how I can access the elements of #ports. Many thanks!
P.S. I apologize for the length of this post. It is my first question on stackoverflow.
I was going to tell you that Data::Dumper can help you sort out Perl data structures, but Data::Dumper can also tell you about your first problem:
Here's what happens when you sign open-curly + close-curly ( '{}' ) to a hash:
use Data::Dumper ();
my %DEVICE_INFORMATION = {}; #global hash
print Dumper->Dump( [ \%DEVICE_INFORMATION ], [ '*DEVICE_INFORMATION ' ] );
Here's the output:
%DEVICE_INFORMATION = (
'HASH(0x3edd2c)' => undef
);
What you did is you assigned the stringified hash reference as a key to the list element that comes after it. implied
my %DEVICE_INFORMATION = {} => ();
So Perl assigned it a value of undef.
When you assign to a hash, you assign a list. A literal empty hash is not a list, it's a hash reference. What you wanted to do for an empty hash--and what is totally unnecessary--is this:
my %DEVICE_INFORMATION = ();
And that's unnecessary because it is exactly the same thing as:
my %DEVICE_INFORMATION;
You're declaring a hash, and that statement fully identifies it as a hash. And Perl is not going to guess what you want in it, so it's an empty hash from the get-go.
Finally, my advice on using Data::Dumper. If you started your hash off right, and did the following:
my %DEVICE_INFORMATION; # = {}; #global hash
my #ports = ( 1, 2, 3 );
# notice that I just skipped the interim structure of #storage
# and assigned it as a literal
# * Perl has one of the best literal data structure languages out there.
$DEVICE_INFORMATION{name} = [ 'banana', \#ports, '0' ];
print Data::Dumper->Dump(
[ \%DEVICE_INFORMATION ]
, [ '*DEVICE_INFORMATION' ]
);
What you see is:
%DEVICE_INFORMATION = (
'name' => [
'banana',
[
1,
2,
3
],
'0'
]
);
So, you can better see how it's all getting stored, and what levels you have to deference and how to get the information you want out of it.
By the way, Data::Dumper delivers 100% runnable Perl code, and shows you how you can specify the same structure as a literal. One caveat, you would have to declare the variable first, using strict (which you should always use anyway).
You update #ports properly.
Your print statement accesses $storage[1] (reference to #ports) in wrong way.
You may use syntax you have used in push.
print $DEVICE_INFORMATION{'name'}[0], ";",
join( ':', #{$DEVICE_INFORMATION{'name'}[1]}), ";",
$DEVICE_INFORMATION{'name'}[2], "\n";
print "Number of ports: ", scalar(#{$DEVICE_INFORMATION{'name'}[1]})),"\n";
print "First port: ", $DEVICE_INFORMATION{'name'}[1][0]//'', "\n";
# X//'' -> X or '' if X is undef