Epigene
Epigene

Reputation: 3908

How to set many variables with gets

I would love to set three variables a, b and c from a single gets line. For example, user entering a line of space-delimited numbers "1 2.2 -3.14" would set a to 1, b to 2.2 and c to -3.14 respectively. I achieve this like so:

input = gets.strip.split
a,b,c = input[0].to_f,input[1].to_f,input[2].to_f

Is there a more elegant way to assign array entries to a range of variables? Perhaps something with a splat and a cycle?

input.each {|entry| *(a..z) = entry }

Upvotes: 1

Views: 63

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110685

str = "scan may be 1 useful if 2.2 the string may contain -3.14 other stuff"

arr = []
str.scan(/-?\d*(?:\d|\.\d|\d\.)\d*/) { |s| arr << s.to_f }
arr #=> [1.0, 2.2, -3.14]

The regex extracts the embedded numbers that have zero or one decimal points.

Considering that you are using gets to obtain str, I've chosen to use arr = rather than a,b,c = so I can make sure the correct number of floats have been returned:

if arr.size == 3
  a,b,c = arr
else
  <raise exception>
end

With v1.9+ you could save a line (just saying, not advocating) by using Object#tap:

arr = [].tap { |a| str.scan(/-?\d*(?:\d|\.\d|\d\.)\d*/) { |s| a << s.to_f } }

Upvotes: 0

Uri Agassi
Uri Agassi

Reputation: 37409

a,b,c = "1 2.2 -3.14".split.map(&:to_f)
# => [1.0, 2.2, -3.14]
b
# => 2.2

Upvotes: 4

Related Questions