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.