Dealing with numbers

Hello,
I want to interrogate SVG (graphic) files. I’m doing so so that I can
modify the width and height of these graphics. So, of course, first
thing I do is a scan for those values. No problem. But, if I want to do
anything with those values, it won’t let me. It fails, basically telling
me that it can’t do an fdiv with an array. Well, yeh, when you do a
.scan, you end up with an array. But, I don’t know how to make that into
a number. Sometimes these numbers are integers; sometimes they’re
floating point numbers. It fails on my height.fdiv(width) statement.

I’ve tried doing .to_f, but, that doesn’t work either. How does one do a
simple search for numbers in a file and end up with numbers, not an
array?

Thanks!

Dir.chdir(‘F:/workflows/filetrain/out/SVG’)
Dir.glob(’.svg’).each do |svgfile|
contents = File.read(svgfile)
width = contents.scan(/width="(\d+.
\d*)/)
height = contents.scan(/height="(\d+.\d)/)

puts width
puts height

ratio = height.fdiv(width)

puts ratio

puts “Ratio is: #{ratio}”

#ratio = 9.234.fdiv(2)
#puts “ratio is: #{ratio}”
end

Your RegExps contain a group, so String#scan will return an Array of
Arrays - each sub-Array contains the captured group(s). For example:

irb:001:0> ‘width=“5.5”’.scan(/width="(\d+.\d)/)
=> [[“5.5”]]
irb:002:0> ‘width=“5.5”, width=“4”’.scan(/width="(\d+.\d)/)
=> [[“5.5”], [“4”]]

And each captured group is still a String, so you’ll need to convert
them to Numerics before the division.

Quick fix, assuming you only care about the first match:

width = contents.scan(/width="(\d+.\d)/).flatten.first.to_f
height = contents.scan(/height="(\d+.\d)/).flatten.first.to_f

Hello Peter,

Is there a ruby library for processing svgs? You can look at
ruby-toolbox:

It seems like it would be a good idea to make use of the svg/xml file
format instead of treating the file as text. But anyway, this isn’t
really the problem.

You have an array of string arrays being returned from String#scan and
want to coerce the first element of the array into a Float? Because, if
that’s what you want to do, you need to flatten the array first.
Afterwards, calling String#to_f should work. Maybe your regular
expression is broken?

You probably don’t need to worry about matching on numbers (digits) in
the regex, because you want to match on “width=” and then get everything
in the first set of inverted commas following. Then you try and coerce
the string to a float.

Maybe something like:

contents.scan(/width="([^"]*)"/).flatten[0].to_f

Here you need to know that the first element in the array is the svg
width attribute you want to change.

You probably want to think about using Float(“12.3”) if you’re worried
about whether or not you have a string representation of a number.

I’m not sure why you’re using fdiv? Hope I haven’t misunderstood
something.

To be honest, if this doesn’t work quickly, you’re heading towards regex
hell.

Gordon Witter wrote in post #1184172:

Your RegExps contain a group, so String#scan will return an Array of
Arrays - each sub-Array contains the captured group(s). For example:

irb:001:0> ‘width=“5.5”’.scan(/width="(\d+.\d)/)
=> [[“5.5”]]
irb:002:0> ‘width=“5.5”, width=“4”’.scan(/width="(\d+.\d)/)
=> [[“5.5”], [“4”]]

And each captured group is still a String, so you’ll need to convert
them to Numerics before the division.

Quick fix, assuming you only care about the first match:

width = contents.scan(/width="(\d+.\d)/).flatten.first.to_f
height = contents.scan(/height="(\d+.\d)/).flatten.first.to_f

Wow! That worked. Thanks a lot, Gordon. I’ve never heard of “flatten”
before. What is the significance of “first” here? And, what do you mean
by the “first match?” There’s only one number after “width” and one
number after “height.”

Cheers. And, thanks again.
Peter

Peter, there are quite possibly many occurrences of the string “width”
in an svg file and therefore quite possibly many elements in the array
you get back from String#scan.




SVG

Joe Gain wrote in post #1184178:

Peter, there are quite possibly many occurrences of the string “width”
in an svg file and therefore quite possibly many elements in the array
you get back from String#scan.




SVG

I see. Thanks. So, that’s what was meant by “first.”