Bug or feature? Weird indentation breaks ruby hashes declaration - ruby

I quite like this indentation style:
hash =
[ "bla" => :bla
, "bli" => :bli
, "blo" => :blo
]
but Ruby does not like that so much.
This is OK:
{ 'a' => 1, 'b' => 2 }
#=> {"a"=>1, "b"=>2}
But this:
{ 'a' => 1
, 'b' => 2 }
yields
-:2: syntax error, unexpected ',', expecting '}'
, 'b' => 2 }
^
-:2: syntax error, unexpected =>, expecting end-of-input
, 'b' => 2 }
^
Is intended by the author or is it a weird bug?

You could add a \ to each line:
hash =
[ "bla" => :bla \
, "bli" => :bli \
, "blo" => :blo \
]
#=> [{"bla"=>:bla, "bli"=>:bli, "blo"=>:blo}]

Just move the commas before the line breaks, and ruby is happy again:
hash =
[ "bla" => :bla,
"bli" => :bli,
"blo" => :blo
]
#=> [{"bla"=>:bla, "bli"=>:bli, "blo"=>:blo}]

Related

How can I do a ruby method that converts morse code into numbers?

I made this ruby method to convert numbers to morse code and it works, but now I'm trying to do the reverse (convert a morse code input into numbers), and I can't figure out how.
def convert(morse_code)
morse_code = {
"1" => ".----",
"2" => "..---",
"3" => "...--",
"4" => "....-",
"5" => ".....",
"6" => "-....",
"7" => "--...",
"8" => "---..",
"9" => "----.",
"0" => "-----"
}
#converted = gets.chomp().downcase.gsub(/\w/, morse_code)
end
puts convert(#converted)
I tried to change the places of the strings in the hash but it actually won't work.
What I've tried so far:
def convert(morse_code)
morse_code = {
'.----': '1', '..---': '2',
'...--': '3', '....-': '4',
'.....': '5', '-....': '6',
'--...': '7', '---..': '8',
'----.': '9', '-----': '0'
}
#converted = gets.chomp().gsub(/\w/, morse_code)
end
puts convert(#converted)
You're redefining the parameter morse_code with your hash, so your param is useless.
use => to have strings as key in hash, like { 'key' => 'value' }
At the end, it looks better like this:
MORSE_CODE_TO_NUMBERS = {
'.----' => 1, '..---' => 2,
'...--' => 3, '....-' => 4,
'.....' => 5, '-....' => 6,
'--...' => 7, '---..' => 8,
'----.' => 9, '-----' => 0
}
def convert_numbers_to_morse
puts 'Enter your morse phrase:'
msg = gets
word_array = msg.split
word_array_converted = word_array.map{|code| MORSE_CODE_TO_NUMBERS[code]}
word_array_converted.join(' ')
end
puts convert_numbers_to_morse

Mongo Group function call in Ruby

I have a mongodb collection like this
{"assigneeId" => 1000, "status" => 3, "starttime" => "2014 Feb 25", "numofdays => 6}
{"assigneeId" => 1000, "status" => 2, "starttime" => "2014 Jan 10", "numofdays => 6}
{"assigneeId" => 1000, "status" => 3, "starttime" => "2014 Jan 1", "numofdays => 20}
I wrote a MongoDB query to group the above collection with assigneeId whose status is 3 and add the value of numofdays like this
db.events.group ( { key: {assigneeId:1}, cond: {status: {$gte: 3}}, reduce: function (curr, result) {result.total++; result.numofdays += curr.numofdays;}, initial: {total:0, numofdays:0} })
This gives the output as expected from the Mongodb cli.
When I write the ruby code for executing the same query, I could not make it work. Am getting lot of different hits for similar problem but none of the format seems to work. I could not go past the syntax error in ruby for grouping function. Please note I am not using mongoid. If I could get this work with Aggregation framework, that is also fine with me.
This is the ruby query I wrote and the error for the same.
#events_h.group (
:cond => {:status => { '$in' => ['3']}},
:key => 'assigneeId',
:initial => {count:0},
:reduce => "function(x, y) {y.count += x.count;}"
)
Error I am getting
analyze.rb:43: syntax error, unexpected ',', expecting ')'
out = #events_h.group (["assigneeId"], { }, { }, "function() { }")
^
analyze.rb:43: syntax error, unexpected ')', expecting keyword_end
analyze.rb:83: syntax error, unexpected end-of-input, expecting keyword_end
Any help is much appreciated.
Thanks
The following test includes solutions for using both methods, group and aggregate.
I recommend that you use aggregate, it is faster and avoids JavaScript and consuming a V8 engine.
Hope that this helps.
test.rb
require 'mongo'
require 'test/unit'
class MyTest < Test::Unit::TestCase
def setup
#events_h = Mongo::MongoClient.new['test']['events_h']
#docs = [
{"assigneeId" => 1000, "status" => 3, "starttime" => "2014 Feb 25", "numofdays" => 6},
{"assigneeId" => 1000, "status" => 2, "starttime" => "2014 Jan 10", "numofdays" => 6},
{"assigneeId" => 1000, "status" => 3, "starttime" => "2014 Jan 1", "numofdays" => 20}]
#events_h.remove
#events_h.insert(#docs)
end
test "group" do
result = #events_h.group(
:cond => {:status => {'$in' => [3]}},
:key => 'assigneeId',
:initial => {numofdays: 0},
:reduce => "function(x, y) {y.numofdays += x.numofdays;}"
)
assert_equal(26, result.first['numofdays'])
puts "group: #{result.inspect}"
end
test "aggregate" do
result = #events_h.aggregate([
{'$match' => {:status => {'$in' => [3]}}},
{'$group' => {'_id' => '$status', 'numofdays' => {'$sum' => '$numofdays'}}}
])
assert_equal(26, result.first['numofdays'])
puts "aggregate: #{result.inspect}"
end
end
$ ruby test.rb
Loaded suite test
Started
aggregate: [{"_id"=>3, "numofdays"=>26}]
.group: [{"assigneeId"=>1000.0, "numofdays"=>26.0}]
.
Finished in 0.010575 seconds.
2 tests, 2 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
189.13 tests/s, 189.13 assertions/s

Hash declaration syntax error in irb

1. { :a => 10 } #=> no error
2. { a: 10 } #=> no error
3. { :"str" => 10 } #=> no error
4. { "str": 10 } #=> syntax error, unexpected ':', expecting =>
Isn't 4. same as 2? Why 2 is working and 4 throws syntax error?
My understanding is that {"key": value} is not a valid syntax as it is not clear whether it means {:"key" => value} or {"key" => value}
There is a discussion on this here. Quote from Matz in the discussion
| Iff {'key': 'value'} means {:key => 'value'} I have no objection.
| Won't that be misleading? I think the OP wants {'key': 'value'} to mean {'key' => 'value}
But considering the fact that {key: "value"}
is a shorthand for {:key => "value"}, {"key": "value"} should be a
shorthand for {:"key" => "value"}. Besides that, since it reminds me
JSON so much, making a: and "a": different could cause more confusion
than the above misleading.
matz.
Hash: Hashes allow an alternate syntax form when your keys are always symbols.
options = { :font_size => 10, :font_family => "Arial" }
You could write it as:
options = { font_size: 10, font_family: "Arial" }
In your first 3 cases all are symbols in key position,but the fourth is a string instance,not the symbol instance as key.That's the reason 4th case is invalid Ruby syntax.
{ :a => 10 }.keys[0].class # => Symbol
{ a: 10 }.keys[0].class # => Symbol
{ :"str" => 10 }.keys[0].class # => Symbol
No. (1) is standard symbol, (2) is shorthand 1.9 syntax for symbol-key hashes, (3) is shorthand for "str".to_sym, (4) does not exist and you should use the hashrocket.

Ruby loops. Hash into string

I am working with Ruby. I need to grab each key/value and put it into a string.
So far I have:
values = ['first' => '1', 'second' => '2']
#thelink = values.collect do | key, value |
"#{key}=#{value}&"
end
When I print #thelink I see:
first1second2=&
But Really what I want is
first=1&second=2
Could anybody help/explain please?
There is something subtle you are missing here {} vs [].
See the below taken from IRB tests:
irb(main):002:0> {'first' => 1, 'second' => 2}
=> {"second"=>2, "first"=>1}
irb(main):003:0> ['first' => 1, 'second' => 2]
=> [{"second"=>2, "first"=>1}]
irb(main):004:0> {'first' => 1, 'second' => 2}.class
=> Hash
irb(main):005:0> ['first' => 1, 'second' => 2].class
=> Array
Similar to this:
irb(main):006:0> {'first' => 1, 'second' => 2}.collect { |key,value| puts "#{key}:#{value}" }
second:2
first:1
=> [nil, nil]
irb(main):007:0> ['first' => 1, 'second' => 2].collect { |key,value| puts "#{key}:#{value}" }
second2first1:
=> [nil]
The array has a single element (a hash) that, as a string, is everything concatenated. This is the important thing to note here.
On the other hand, the hash iterates by handing you the key/value pairs that you are expecting.
Hope that helps.
I think your code has a typo (a hash is delimited by {} not by []). Try this
values = {'first' => '1', 'second' => '2'}
r = values.map{|k,v| "#{k}=#{v}"}.join('&')
puts r
#shows: first=1&second=2

Ruby - method parameters

My method:
def my_method=(attributes, some_option = true, another_option = true)
puts hello
end
When i try to call this, i get such error:
my_method=({:one => 'one', :two => 'two'}, 1, 1)
#you_code.rb:4: syntax error, unexpected ',', expecting ')'
#my_method=({:one => 'one', :two => 'two'}, 1, 1)
^
What's the problem?
Method with suffix punctuation = can have only one argument.
Otherwise, you must use send to invoke with multiple parameters.
send :'my_method=', {:a => 1}, 1, 1
Don't use parenthesis when invoking a method using the = syntactic sugar.
Invoke it like this:
mymethod= {:one => 'one', :two => 'two'}, 1, 1

Resources