Print specified value from hash Ruby - ruby

I'd like to know how get the specified field from Hash.
{"codeid"=>120023, "eppocode"=>"1BOBO", "prefname"=>"Pikant", "level"=>7}
I have this Hash and i want to get level field (7) becouse i need to compare it afterwards
Thanks!

Using Standard Hash Accessors
You can use either Hash#[] or Hash#dig for this. There are other ways to do this too such as pattern matching, but those are overkill for what you're doing.
For example:
h = {
"codeid" => 120023,
"eppocode" => "1BOBO",
"prefname" => "Pikant",
"level" => 7,
}
h["level"]
#=> 7
h.dig "level"
#=> 7

Like this:
hash = {"codeid"=>120023, "eppocode"=>"1BOBO", "prefname"=>"Pikant", "level"=>7}
hash["level"]
#=> 7

Related

Object attributes to JavaScript-like hash?

This is kind of an odd question, but I don't .......
I overcomplicated the original question. If you want to see the original question, look through the previous edits. Here's my revised question by combining my two previous questions, as simple as I can explain it:
I have an object. The object can have (x) amount of fields and all of the fields and values can be different. Example:
#<User name="John", height=75> or #<Comment title="First!">
I'm using a gem/db requires a specific format for queries. This is the format that the query MUST have: CREATE (u:User{attribute: "Some att.", another_att: 32}) and so on and so forth. Notice the JavaScript-like hash it uses for its values.
I'm trying to interpolate an object's attributes into the query. But I don't know how to map the correct fields and values into the query. Here's an example of what I start with and what I want to end with:
object = #<User name="John", height=75> =>
"CREATE (u:User{name: "John", height: 75})"
What's the simplest way to achieve this? Thanks to everyone who's helped so far.
Note that it is possible to convert the attributes to a Ruby hash: {:name => "John", :height => 75}, (as explained in the original question) but it was too confusing to change that hash to the syntax in the query, so I've backtracked and simplified my question.
It is very unlikely that the literal is the problem. The JSON-style syntax
was introduced in Ruby 1.9 as a literal abbreviation for the longer
"hashrocket" style.
> {name: 'John'} == {:name => 'John'}
=> true
Figured it out by going through the Ruby docs. It was way simpler than it seemed. The .collect method (or map) can be used to map each value and field to an interpolated string that can be put into a query. Example:
hash = {first_name: 'John', last_name: 'Smith'}
hash.collect {|k, v| "#{k}: #{v}"}
=> ["first_name: John", "last_name: Smith"]
This doesn't make sense. There has to be something else going on here.
A hash is a hash is a hash, it doesn't matter what syntax you used to create it, it's still the exact same hash. Those four are 100% equivalent (and if they aren't, that's a bug in your Ruby implementation):
hash = { name: 'John' }
hash = { :name => 'John' }
hash = {}
hash[:name] = 'John'
hash = Hash.new
hash[%Q|name|.to_sym] = %w#John#.first
There is absolutely no difference between them. There is no such thing as a "Hashrocket Hash" or "JSON-style Hash". There is a difference between the literals used to construct those hashes, but that difference only exists at parse time. At runtime, they are just as identical as 16, 0x10 and 020 are.

Fetching all the values for keys matching a regular expression

I'm looking for a Ruby in-memory key-value store that allows me to select all values for the keys that match a regular expression.
I have looked online but I can't find something the does what I need.
Any suggestion?
Thanks
Update
After reviewing my question I noticed I wasn't probably very clear so, also because someone of you guys asked got it, here an example.
I'm currently using Daybreak in my app so I use it for the example but it does not work.
require 'daybreak'
db = Daybreak::DB.new "example.db"
db['prefix_foo'] = 'first'
db['prefix_bar'] = 'second'
db['doo'] = 'third'
db.magic('prefix') #=> [ db['prefix_foo'], db['prefix_bar']]
Or
db.magic('prefix') #=> ['prefix_foo', 'prefix_bar']
I'd rather not to use a "naked" hash.
Thanks again for your help.
str = {:make => "bmw", :year => "2003"}
str.select{|k,v| k =~ /ak/}
#=> {:make=>"bmw"}
str.select{|k,v| k =~ /ak/}.values #=> get only values
#=> ["bmw"]

How to convert a ruby integer into a symbol

I have a Ruby array like this
q_id = [1,2,3,4,5,...,100]
I want to iterate through the array and convert into a hash like this
{
:1 => { #some hash} ,
:2 => { #another hash},
...
:100 => {#yet another hash}
}
What is the shortest and most elegant way to accomplish this?
[EDIT : the to_s.to_sym while being handy is not how I want it. Apologies for not mentioning it earlier.]
For creating a symbol, either of these work:
42.to_s.to_sym
:"#{42}"
The #inspect representation of these shows :"42" only because :42 is not a valid Symbol literal. Rest assured that the double-quotes are not part of the symbol itself.
To create a hash, there is no reason to convert the keys to symbols, however. You should simply do this:
q_id = (1..100).to_a
my_hash_indexed_by_value = {}
q_id.each{ |val| my_hash_indexed_by_value[val] = {} }
Or this:
my_hash = Hash[ *q_id.map{ |v| [v,{}] }.flatten ]
Or this:
# Every time a previously-absent key is indexed, assign and return a new hash
my_hash = Hash.new{ |h,val| h[val] = {} }
With all of these you can then index your hash directly with an integer and get a unique hash back, e.g.
my_hash[42][:foo] = "bar"
Unlike JavaScript, where every key to an object must be a string, Hashes in Ruby accept any object as the key.
To translate an integer into a symbol, use to_s.to_sym .. e.g.,:
1.to_s.to_sym
Note that a symbol is more related to a string than an integer. It may not be as useful for things like sorting anymore.
Actually "symbol numbers" aren't a thing in Ruby (try to call the to_sym method on a number). The benefit of using symbols in a hash is about performance, since they always have the same object_id (try to call object_id on strings, booleans, numbers, and symbols).
Numbers are immediate value and, like Symbol objects, they always have the same object_id.
Anyway, using the new hash syntax implies using symbols as keys, but you can always use the old good "hash rocket" syntax
awesome_hash = { 1 => "hello", 2 => "my friend" }
Read about immediate values here:
https://books.google.de/books?id=jcUbTcr5XWwC&pg=PA73&lpg=PA73&dq=immediate+values+singleton+method&source=bl&ots=fIFlAe8xjy&sig=j7WgTA1Cft0WrHwq40YdTA50wk0&hl=en&sa=X&ei=0kHSUKCVB-bW0gHRxoHQAg&redir_esc=y#v=onepage&q&f=false
If you are creating a hard-coded constant numeric symbol, there's a simpler way:
:'99'
This produces the same results as the more complex methods in other answers:
irb(main):001:0> :'99'
=> :"99"
irb(main):002:0> :"#{99}"
=> :"99"
irb(main):003:0> 99.to_s.to_sym
=> :"99"
Of course, this will not work if you're dynamically creating a symbol from a variable, in which case one of the other two approaches is required.
As already stated, :1 is not a valid symbol. Here's one way to do what you're wanting, but with the keys as strings:
Hash[a.collect{|n| [n.to_s, {}] }]
An array of the objects you want in your hash would be so much easier to use, wouldn't it? Even a hash of integers would work pretty well, wouldn't it?
u can use
1.to_s.to_sym
but this will make symbols like :"1"
You can make symbolic keys with Hash[]:
a = Hash[(1..100).map{ |x| ["#{x}".to_sym, {}] }]
Check type of hash keys:
puts a.keys.map(&:class)
=>
Symbol
...
Symbol
Symbol

Ruby: How to loop through an object that may or may not be an array?

I have an each method that is run on some user-submitted data.
Sometimes it will be an array, other times it won't be.
Example submission:
<numbers>
<number>12345</number>
</numbers>
Another example:
<numbers>
<number>12345</number>
<number>09876</number>
</numbers>
I have been trying to do an each do on that, but when there is only one number I get a TypeError (Symbol as array index) error.
I recently asked a question that was tangentally similar. You can easily force any Ruby object into an array using Array.
p Array([1,2,3]) #-> [1,2,3]
p Array(123) #-> [123]
Of course, arrays respond to each. So if you force everying into an array, your problem should be solved.
A simple workaround is to just check if your object responds to :each; and if not, wrap it in an array.
irb(main):002:0> def foo x
irb(main):003:1> if x.respond_to? :each then x else [x] end
irb(main):005:1> end
=> nil
irb(main):007:0> (foo [1,2,3]).each { |x| puts x }
1
2
3
=> [1, 2, 3]
irb(main):008:0> (foo 5).each { |x| puts x }
5
=> [5]
It looks like the problem you want to solve is not the problem you are having.
TypeError (Symbol as array index)
That error tells me that you have an array, but are treating it like a hash and passing in a symbol key when it expects an integer index.
Also, most XML parsers provide child nodes as array, even if there is only one. So this shouldn't be necesary.
In the case of arguments to a method, you can test the object type. This allows you to pass in a single object or an array, and converts to an array only if its not one so you can treat it identically form that point on.
def foo(obj)
obj = [obj] unless obj.is_a?(Array)
do_something_with(obj)
end
Or something a bit cleaner but more cryptic
def foo(obj)
obj = [*obj]
do_something_with(obj)
end
This takes advantage of the splat operator to splat out an array if it is one. So it splats it out (or doesn't change it) and you can then wrap it an array and your good to go.
I was in the same position recently except the object I was working with was either a hash or an array of hashes. If you are using Rails, you can use Array.wrap because Array(hash) converts hashes to an array.
Array({foo: "bar"}) #=> [[:foo, "bar"]]
Array.wrap({foo: "bar"}) #=> [{:foo=>"bar"}]
Array.wrap(123) #=> [123]
Array.wrap([123]) #=> [123]
I sometimes use this cheap little trick:
[might_be_an_array].flatten.each { |x| .... }
Use the splat operator:
[*1] # => [1]
[*[1,2]] # => [1,2]
Like Mark said, you're looking for "respond_to?" Another option would be to use the conditional operator like this:
foo.respond_to? :each ? foo.each{|x| dostuff(x)} : dostuff(foo);
What are you trying to do with each number?
You should try to avoid using respond_to? message as it is not a very object oriented aproach.
Check if is it possible to find in the xml generator code where it is assigning an integer value when there is just one <"number"> tag and modify it to return an array.
Maybe it is a complex task, but I would try to do this in order to get a better OO design.
I don't know much anything about ruby, but I'd assume you could cast (explicitly) the input to an array - especially given that if the input is simply one element longer it's automatically converted to an array.
Have you tried casting it?
If your input is x, use x.to_a to convert your input into an array.
[1,2,3].to_a
=> [1, 2, 3]
1.to_a
=> [1]
"sample string".to_a
=> ["sample string"]
Edit: Newer versions of Ruby seem to not define a default .to_a for some standard objects anymore. You can always use the "explicit cast" syntax Array(x) to achieve the same effect.

hash as def argument

Is the following possible in any way? I keep running into a odd number list for Hash
def thores_hammer(bling)
hammer_bling = { bling }
end
thores_hammer :rubys => 5,
:emeralds => 5,
:souls => 333
Thanks ahead of time.
The reason you're running into an error is that the
Hash is implicitly created when the thores_hammer method
is invoked - so when you do { bling } you're creating a hash
with only one key (which is itself a hash) and no value. Thus the
error.
All you need to do is drop the curly braces:
irb> def thores_hammer(bling)
hammer_bling = bling
end
#=> nil
irb> thores_hammer :rubys => 5,
:emeralds => 5,
:souls => 333
#=> {:rubys=>5, :emeralds=>5, :souls=>333}
What you may be intending to do is make a copy of the Hash which could be done as:
def thores_hammer(bling)
hammer_bling = bling.dup
end
It might be a good idea to make a copy if you're intending to use the Hash for a long period of time and aren't sure if modifying the copy the method was given is a good idea because it could be used in other places.
Also, there are several different uses for curly braces within Ruby such as declaring blocks.
Try this:
def thores_hammer(bling)
hammer_bling = bling
end
thores_hammer Hash[:rubys => 5, :emeralds => 5, :souls => 333]

Resources