Where do I put the ".to_f"?

Hello,
I need to do some simply computations on numbers pulled from a file. I
get the numbers using “scan.” I’ve proven that I can get the numbers
alright. But, I need to do some division and multiplication on those
numbers, and, to be accurate, the numbers need to be floating numbers,
not integers. So, I’ve tried everything, or so I think, and Ruby keeps
complaining about my “.to_f” method. Can someone please tell me where
this .to_f should go?
Thanks,
Peter

Dir.chdir(“K:”)
tifffile = File.basename(ARGV.to_s, “.*”) + “.tif”
info = tiffinfo #{tifffile}
width = info.scan(/Image Width: ([0-9]{1,5})/)
depth = info.scan(/Image Length: ([0-9]{1,5})/)
res = info.scan(/Resolution: [0-9]{1,5}, ([0-9]{1,5}) pixels/inch/)

newwidth = width.to_f / 600 * 6
newdepth = depth.to_f / 600 * 6

I get this from Ruby:
sizer.rb:10: undefined method `to_f’ for [[“5100”]]:Array
(NoMethodError)

Ruby keeps complaining about my “.to_f” method.

What does it say?

I thought initially that you could have some extra whitespace in your
strings but it seems Ruby is pretty tolerant about this stuff:

irb(main):001:0> ‘5.0’.to_f
=> 5.0
irb(main):002:0> ’ 5.0 '.to_f
=> 5.0
irb(main):003:0> ’ 5.0a '.to_f
=> 5.0
irb(main):004:0> ‘a5.0’.to_f
=> 0.0

On 07.01.2008 19:06, Peter B. wrote:

I get this from Ruby:
sizer.rb:10: undefined method `to_f’ for [[“5100”]]:Array
(NoMethodError)

Your error is in using #scan (see the docs for details).

This works better

width = info[/Image Width: ([0-9]{1,5})/, 1].to_f

Cheers

robert

Scan is generally used when you have multiple matches, for example
“abcdefg”.scan(/…/) => [“ab”, “cd”, “ef”].

I think in your case match is better:
Dir.chdir(“K:”)
tifffile = File.basename(ARGV.to_s, “.*”) + “.tif”
info = tiffinfo #{tifffile}
width = info.match(/Image Width: ([0-9]{1,5})/)[1]
depth = info.match(/Image Length: ([0-9]{1,5})/)[1]
res = info.match(/Resolution: [0-9]{1,5}, ([0-9]{1,5})
pixels/inch/)[1]

newwidth = width.to_f / 600 * 6
newdepth = depth.to_f / 600 * 6

And now your code should work as intended. The [1] at the end of the
match
is because match returns an object that can act like an Array of [the
whole
match, the first parenthesis, the second parenthesis, etc…].

The reason you were getting an error before is that you were calling
to_f on
an Array. [4].to_f might be interpreted by a human as 4.to_f but not to
Ruby. And what would ruby do if it was [2, 3, 4].to_f ?

Dan

Robert K. wrote:

On 07.01.2008 19:06, Peter B. wrote:

I get this from Ruby:
sizer.rb:10: undefined method `to_f’ for [[“5100”]]:Array
(NoMethodError)

Your error is in using #scan (see the docs for details).

This works better

width = info[/Image Width: ([0-9]{1,5})/, 1].to_f

Cheers

robert

Thank you very much. Yes, that works perfectly. That whole square
bracket thing you use there is new to me. When you say “see the docs,”
what should I look for? For “String#scan” or for Regex. . . .?

Peter B. wrote:

Dir.chdir(“K:”)
tifffile = File.basename(ARGV.to_s, “.*”) + “.tif”

So “yourscript.rb c:/foo/bar.jpg” would open the file k:/bar.tif? That
seems… wrong to me. But of course I don’t know why you do this - it
might make perfect sense under the circumstances.

info = tiffinfo #{tifffile}
width = info.scan(/Image Width: ([0-9]{1,5})/)

String#scan creates an array of strings (if you have a regex without
capturing
groups) or of arrays (where for each capturing group you have a string
in the
array). For example:

“foo123bar456chunky789bacon”.scan(/\d+/) #=> [“123”,“456”,“789”]
“hi:ho foo:bar”.scan(/(\w+):(\w+)/) #=> [[“hi”,“ho”], [“foo”,“bar”]]
“Image Width: 123”.scan(/Image Width: ([0-9]{1,5})/) #=> [[“123”]]

That’s an array containing an array containing a string. Since you just
want
the string and since there’s only ever gonna be one, you should just use
String#match or String#[]:

width = info[/Image Width: ([0-9]{1,5})/, 1]

If String#[] is used with a regex it will return the substring matching
that
regex. If you also give it a number as second argument, it will only
return
the contents of the nth capturing group (n being the number).

I get this from Ruby:
sizer.rb:10: undefined method `to_f’ for [[“5100”]]:Array
(NoMethodError)

Yes, arrays don’t have a to_f method (since arrays usually contain
multiple
elements and it would be strange to turn that into one single number).
If you use [] like I showed above, you will have a string, which will
have a
to_f method, so this will work.

HTH,
Sebastian

On Jan 7, 2008 12:25 PM, Peter B. [email protected] wrote:

width = info[/Image Width: ([0-9]{1,5})/, 1].to_f

Cheers

robert

Thank you very much. Yes, that works perfectly. That whole square
bracket thing you use there is new to me. When you say “see the docs,”
what should I look for? For “String#scan” or for Regex. . . .?

You want to look at String#[]

Todd

String#scan as you are calling the scan method of a string instance.
String
is known as the receiver.

Dan

Sebastian H. wrote:

Yes, arrays don’t have a to_f method (since arrays usually contain
multiple
elements and it would be strange to turn that into one single number).
If you use [] like I showed above, you will have a string, which will
have a
to_f method, so this will work.

HTH,
Sebastian

This is very cool, what you’ve shown me here. I’ve never used the
String#[] nomenclature before, especially, with the number argument in
it. It’s so simple! Thanks!

Daniel F. wrote:

String#scan as you are calling the scan method of a string instance.
String
is known as the receiver.

Dan

Thanks !

Todd B. wrote:

On Jan 7, 2008 12:25 PM, Peter B. [email protected] wrote:

width = info[/Image Width: ([0-9]{1,5})/, 1].to_f

Cheers

robert

Thank you very much. Yes, that works perfectly. That whole square
bracket thing you use there is new to me. When you say “see the docs,”
what should I look for? For “String#scan” or for Regex. . . .?

You want to look at String#[]

Todd

Yes. Thanks. It’s just that I never knew that String#[] even existed.
It’s a great tool.

On Jan 7, 2008 1:38 PM, Peter B. [email protected] wrote:

Yes. Thanks. It’s just that I never knew that String#[] even existed.
It’s a great tool.

For the record, I’ve never used it and had to look it up myself after
reading this thread :slight_smile:

If you really wanted to, you could write an Enum method that would
traverse the Enum object and try its best to coerce the contained
objects into other objects (like a to_f, for example). It might make
for a good little practice “golf” game – and someone else probably
already has done it – but it could be useful…

[‘a’, 1, ‘b’, [my_object, ‘c’, 5]].to_f
=> [nil, 1.0, nil, [nil, nil, 5.0]]

Todd

Thanks, Dan. So, your nomenclature is more like mine, but, you’ve got
the number arguments at the end – [1]. A beautiful thing.