line.split with some complicating factors...

M

Marc Hoeppner

Hi all,

I've been thinking about this for a while but cant figure out an
efficient (or any actually) way to do the following:

a line contains a list of coordinates (specifying a range) separated by
a "," like so:

50586..50639,50795..51859,60005..60058,60256..61236

Pulling out the separate coordinates via split is of course rather
simple. But, here's the catch...
I not only need the given ranges, but also the stretches in between (I
am pulling the coordinates out of a large text file, so there is no good
way to manipulate the source). So the whole range is in reality
everything between the first and the last number...However, I have to
treat the originally given ranges and the stretches in between
differently. The given ranges are printed in upcase, the parts not
specified in downcase. Now, a way this could look like would be:

E50586..50639,50640..50795,E50795..51859,..

The "E" at the beginning is then used to identify the original ranges
and as a condition for printing in upcase.

So, my point being...I have absolutely no clue how to do this. The
procedure would have to split the given ranges but also immediately
write the missing ranges in the correct order.

If anyone has an idea how to approach this, I could really need some
advice here.

Cheers,

Marc
 
M

Marc Hoeppner

edit: by up- and downcase I am referring to the way I want to puts the
result, not the format of the source..there it is all downcase, so no
way to use that to distinguish anything
 
D

dblack

Hi --

Hi all,

I've been thinking about this for a while but cant figure out an
efficient (or any actually) way to do the following:

a line contains a list of coordinates (specifying a range) separated by
a "," like so:

50586..50639,50795..51859,60005..60058,60256..61236

Pulling out the separate coordinates via split is of course rather
simple. But, here's the catch...
I not only need the given ranges, but also the stretches in between (I
am pulling the coordinates out of a large text file, so there is no good
way to manipulate the source). So the whole range is in reality
everything between the first and the last number...However, I have to
treat the originally given ranges and the stretches in between
differently. The given ranges are printed in upcase, the parts not
specified in downcase. Now, a way this could look like would be:

E50586..50639,50640..50795,E50795..51859,..

The "E" at the beginning is then used to identify the original ranges
and as a condition for printing in upcase.

So, my point being...I have absolutely no clue how to do this. The
procedure would have to split the given ranges but also immediately
write the missing ranges in the correct order.

If anyone has an idea how to approach this, I could really need some
advice here.

I'm not sure if this is an exact fit but see if it helps. This is
based on the first string (no E characters, etc.):

ranges = str.scan(/(\d+)\.\.(\d+)/).map {|a,b| a.to_i..b.to_i }
betweens = str.scan(/(\d+),(\d+)/).map {|a,b| (a.to_i+1)..b.to_i-1 }


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
M

Marc Hoeppner

ranges = str.scan(/(\d+)\.\.(\d+)/).map {|a,b| a.to_i..b.to_i }
betweens = str.scan(/(\d+),(\d+)/).map {|a,b| (a.to_i+1)..b.to_i-1 }


David

Took me a bit, but got it working - perfect, thanks a lot!
 
B

Bernard Kenik

Marc said:
Took me a bit, but got it working - perfect, thanks a lot!

an alternate way which might be clearer would

a = 50586..50639,50795..51859,60005..60058,60256..61236
b = []
0.upto(a.size - 2) do |i|
c = a.last + 1
d = a[i+1].first - 1
b << (c..d)
end

p a =>
[50586..50639, 50795..51859, 60005..60058, 60256..61236]

p b =>
[50640..50794, 51860..60004, 60059..60255]
 
W

Wolfgang Nádasi-donner

Marc said:
a line contains a list of coordinates (specifying a range) separated by
a "," like so:

50586..50639,50795..51859,60005..60058,60256..61236

Now, a way this could look like would be:

E50586..50639,50640..50795,E50795..51859,..

I see that the problem is already solved, but in Ruby I always have the
feeling, that there must be something like a "one-liner" for nearly all
problems.

Unfortunately I ended only with "something" like a one-liner.
intxts = [ "50586..50639,50795..51859,60005..60058,60256..61236",
"0..10,50000..50100,50101..51000,60005..60058,60059..61236" ]
def put(a);(a = a.push(a.shift))[0];end
intxts.each do |intxt|
pre = ['', 'E']
p intxt.split(',').collect{|e|e.split('..').collect{|v|Integer(v)}}.
inject([[],0]){|c,e|
c[1]==0 ? (c[0]<<e;c[1]=e[1]+1) : (
c[1]==e[0] ? (c[0]<<[0,0]<<e) : (c[0]<<[c[1],e[0]-1]<<e)
c[1]=e[1]+1);c
}.at(0).collect{|r|put(pre)+r.join('..')}.join(',').gsub(/0\.\.0,/,'')
end
"E50586..50639,50640..50794,E50795..51859,51860..60004,E60005..60058,60059..60255,E60256..61236"
"E0..10,11..49999,E50000..50100,E50101..51000,51001..60004,E60005..60058,E60059..61236"

Sorry, but it is a Ruby generated addiction...

Wolfgang Nádasi-Donner
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top