Ruby Ternary Inside Hash Build - ruby

Looking for a way to include a ternary conditional inside a hash assignment.
a = 5
h = {}
h[:alpha] => a > 3 ? true : false # edited twice
h[:alpha] => (a > 3 ? true : false) # edited twice
There has to be a way of shortening this up.

Almost always when a beginner is using a literal true or false, that is unnecessary. In this case, you don't need a ternary at all.
a = 5
h = {}
h[:alpha] = a > 3
h[:alpha] # => true

You need to assign the values by using = (assignment operator) and not =>.
Try:
h[:alpha] = a > 3 ? true : false
Example:
2.1.2-perf :001 > a = 5
=> 5
2.1.2-perf :002 > h = {}
=> {}
2.1.2-perf :005 > h[:alpha] = (a > 3 ? true : false)
=> true
2.1.2-perf :006 > h[:alpha]
=> true
Edit (As per your comments):
2.1.2-perf :014 > user = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
2.1.2-perf :016 > user[1] == "solo" ? "#{user[2]} #{user[3]} (s)" : "#{user[4]} (g)"
=> "5 (g)"

Related

Ruby strange behaviour while single assigning variables in a single line

How local variable num_1 is assigned as [1, 2]?. Isn't that suppose to be 1?
2.1.5 :121 > num_1 = 1, num_2 = 2
=> [1, 2]
2.1.5 :122 >
2.1.5 :123 >
2.1.5 :124 > num_1
=> [1, 2]
2.1.5 :125 >
2.1.5 :126 >
2.1.5 :127 > num_2
=> 2
2.1.5 :128 >
It first assigns 2 to num_2, then returns a value and puts it into an array that is assigned to num_1
[11] pry(main)> num_1 = 1, num_2 = 2
=> [1, 2]
[12] pry(main)> num_1 = 1, (num_2 = 2)
=> [1, 2]
[13] pry(main)> num_1 = [1, (num_2 = 2)]
=> [1, 2]
If you want to assign two variables in one line, use a semicolon:
[14] pry(main)> num_1 = 1; num_2 = 2
=> 2
[15] pry(main)> num_1
=> 1
[16] pry(main)> num_2
=> 2
While it is valid Ruby code to do single-line parallel assignments like this:
a, b, c, d = 'foo', 'bar', 'baz', 'foobar'
it is considered "bad style". See Parallel Assignment in the The Ruby Style Guide.

Ruby: How can I dynamically build a hash from user input

I have a hash like this below
h = {a: 1, b: 2, c: 3, d: 4.....z: 26}
now user input 1 then I will fetch first 5 if user input 2 then 6 to next 5 means 6 to 11
How can I acheieve this by a best way
h = {a: 1, b: 2, c: 3, d: 4.....z: 26}
user_input = 1
Hash[h.to_a[((user_input - 1) * 5 )..( (user_input * 5) - 1)]]
#=> {:a=>1, :b=>2, :c=>3, :d=>4, :e=>5}
I assume the question concerns an arbitrary hash.
Code
Three choices:
#1
def select_em(h, which_block_5)
select_range = (5*which_block_5 - 4)..(5*which_block_5)
h.select.with_index(1) { |_,i| select_range.cover?(i) }
end
#2
def select_em(h, which_block_5)
select_array = Array.new(5*(which_block_5-1),false) +
Array.new(5,true) +
Array.new(h.size-5*(which_block_5),false)
h.select { select_array.shift }
end
Note
select_array = Array.new(5*(which_block_5-1),false) +
Array.new(5,true) +
Array.new(26-5*(which_block_5),false)
#=> [false, false, false, false, false, true, true, true, true, true,
# false, false, false, false, false, false, false, false, false,
# false, false, false, false, false, false, false]
#3
def select_em(h, which_block_5)
start = 5*which_block_5 - 4
stop = start + 4
h.select.with_index(1) { |_,i| (i==start..i==stop) ? true : false }
end
This method uses Ruby's flip-flop operator.
All of these methods use Hash#select (which returns a hash), not Enumerable#select (which returns an array).
Examples
h = {:a=>1, :b=>2, :c=>3, :d=>4, :e=>5, :f=>6, :g=>7, :cat=>"meow", :dog=>"woof",
:h=>8, :i=>9, :j=>10, :k=>11, :l=>12, :m=>13, :n=>14, :o=>15,
:p=>16, :q=>17, :r=>18, :s=>19, :t=>20, :u=>21, :v=>22, :w=>23,
:x=>24, :y=>25, :z=>26}
select_em(h, 1)
#=> {:a=>1, :b=>2, :c=>3, :d=>4, :e=>5}
select_em(h, 2)
#=> {:f=>6, :g=>7, :cat=>"meow", :dog=>"woof", :h=>8}
select_em(h, 3)
#=> {:i=>9, :j=>10, :k=>11, :l=>12, :m=>13}
select_em(h, 4)
#=> {:n=>14, :o=>15, :p=>16, :q=>17, :r=>18}
Here is what i would do:
char_ary = ('a'..'z').to_a
start_idx = (input - 1) * 5
subary = char_ary.slice(start_idx, 5)
subary.inject({}) do |h, c|
h[c.to_sym] = char_ary.index(c) + 1
h
end
This doesn't need a hash to be defined with all the alphabets.
So you can simply use slice array function to split out things.
alphabets = [*('a'..'z')].collect.with_index{ |key,index| { key => index+1 } }
user_input = 1 # Capture user input here.
part_of_array = alphabets[( (user_input - 1) * 5 )..( (user_input * 5) - 1)]
Converting into simple one hash use the below code.
part_of_array = eval(alphabets[( (user_input - 1) * 5 )..( (user_input * 5) - 1)].to_s.gsub("{","").gsub("}",""))
Let me know if you have any issues.

Is true && true == false?

Am I missing something or is this a bug in ruby?
a = %w(foo bar baz)
a.include? "foo" # => true
a.size == 3 # => true
a.include? "foo" && a.size == 3 # => false
a.include? "foo" && a.size == 3
is evaluated as
a.include? ("foo" && a.size == 3)
and because
"foo" && a.size == 3 #=> true
this is equivalent to
a.include? true
which is false
Is true && true == false?
No.
irb(main):003:0> true && true == false
=> false
What you meant to check is
a.include?("foo") && a.size == 3
Your condition is checking if "foo" && a.size == 3 (which is true because "foo" is neither nil nor false) is included in the array.
The solution of Zack's comment is correct too, but looking a bit unusual:
(a.include? "foo") && a.size == 3
One reason why the whole expression is considered the method's argument in case of missing parentheses is you can do:
puts 3 + 4 * 5 - 6

Return variable rather than the value

I am curious about a feature of the .each method.
a = 1
b = 2
[a,b].each do |x|
puts x
end
Is there a way for ruby to return the variable "a" rather than the value 1?
It doesn't return 1, it returns [1, 2], the each method returns what it iterated over.
> a = 1
=> 1
> b = 2
=> 2
> r = [a, b].each { |x| puts x }
1
2
=> [1, 2]
> p r.inspect
"[1, 2]"
If you're asking if you can "go backwards" from the array value, or the variable inside the iteration block, I don't see how. If you were iterating over a map with key/value pairs, yes.
> m = { a: 1, b: 2}
=> {:a=>1, :b=>2}
> m.each { |k, v| p "#{k} = #{v}" }
"a = 1"
"b = 2"

Single line multiple assignment in ruby

Is it good to assign an empty array in one line ?
arun#arun:~$ irb
irb(main):001:0> a = b = c = []
=> []
irb(main):002:0> b << "one"
=> ["one"]
irb(main):003:0> p a
["one"]
=> nil
Since i expect 'a' to be [] but it show the value of b means "one". Is this expect one ?
I also try with string and integer object.
irb(main):004:0> d = e = f = 0
=> 0
irb(main):005:0> f = 6
=> 6
irb(main):006:0> p d
0
=> nil
irb(main):007:0>
irb(main):007:0> q = w = e = r = "jak"
=> "jak"
irb(main):008:0> e = "kaj"
=> "kaj"
irb(main):009:0> p w
"jak"
=> nil
irb(main):010:0> p e
"kaj"
=> nil
irb(main):011:0>
It is working as i expected. Then why not array ?
What you are doing is assingning [] to c, which you then assign to b, which finally gets assigned to a.
>> a = b = c = []
>> a.object_id
=> 2152679240
>> b.object_id
=> 2152679240
>> c.object_id
=> 2152679240
What you want is
>> a,b,c = [], [], []
=> [[], [], []]
>> a.object_id
=> 2152762780
>> b.object_id
=> 2152762760
>> c.object_id
=> 2152762740
Edit: the examples work because you just go and plain assign a new value (Fixnums can't be mutated anyway). Try modifying the string in-place instead:
>> q = w = e = r = "jak"
=> "jak"
>> e << 'i'
=> "jaki"
>> w
=> "jaki"
In Ruby everything is an object, including [], 0, and "jak" (an instance of Array, Integer, and String, respectively). You are assigning the same object to multiple variables -- if you change that object (b << "one"), then every variable referencing that object will reflect the change. When you use the assignment operator = you are not changing the object -- you are assigning a new object to the variable.
In Michael Kohl's last example (), he is using << which modifies the String object referenced by the variable. That is why the variable still references the same object and all strings referencing that object reflect the change.

Resources