Where do I put the ".to_f" ?

P

Peter Bailey

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)
 
R

Robert Klemme

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)

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
 
O

ole __

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
 
D

Daniel Finnie

[Note: parts of this message were removed to make it a legal post.]

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
 
P

Peter Bailey

Robert said:
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. . . .?
 
T

Todd Benson

Robert said:
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. . . .?

You want to look at String#[]

Todd
 
S

Sebastian Hungerecker

Peter said:
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
 
D

Daniel Finnie

[Note: parts of this message were removed to make it a legal post.]

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

Dan

Robert said:
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. . . .?
 
P

Peter Bailey

Sebastian said:
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!
 
P

Peter Bailey

Todd said:
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.
 
P

Peter Bailey

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

Todd Benson

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 :)

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,113
Latest member
Vinay KumarNevatia
Top