# Line.split with some complicating factors

**URL:** <https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919>\
**Category:** Ruby\
**Created:** [July 20, 2007, 8:16am UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919 "2007-07-20T08:16:23Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![lasastard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/58956e/32.png) [@lasastard](https://www.ruby-forum.com/u/lasastard)\
**Post date:** [July 20, 2007, 8:16am UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919/1 "2007-07-20T08:16:23Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![lasastard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/58956e/32.png) [@lasastard](https://www.ruby-forum.com/u/lasastard)\
**Post date:** [July 20, 2007, 8:18am UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919/2 "2007-07-20T08:18:36Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![lasastard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/58956e/32.png) [@lasastard](https://www.ruby-forum.com/u/lasastard)\
**Post date:** [July 20, 2007, 8:53am UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919/3 "2007-07-20T08:53:57Z")

</div>

Hi –

On Fri, 20 Jul 2007, Marc H. wrote:

> Pulling out the separate coordinates via split is of course rather
> 
> 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

---

<div class="post-metadata">

**Author:** ![lasastard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/58956e/32.png) [@lasastard](https://www.ruby-forum.com/u/lasastard)\
**Post date:** [July 20, 2007, 10:14pm UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919/4 "2007-07-20T22:14:30Z")

</div>

Marc H. wrote:

> > 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!

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[i].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]

---

<div class="post-metadata">

**Author:** ![lasastard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/58956e/32.png) [@lasastard](https://www.ruby-forum.com/u/lasastard)\
**Post date:** [July 20, 2007, 9:47am UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919/5 "2007-07-20T09:47:54Z")

</div>

> 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!

---

<div class="post-metadata">

**Author:** ![lasastard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/58956e/32.png) [@lasastard](https://www.ruby-forum.com/u/lasastard)\
**Post date:** [July 22, 2007, 3:24am UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919/6 "2007-07-22T03:24:58Z")

</div>

Marc H. wrote:

> 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.

> > > > > code \>\>\>\>\>  
> > > > > 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
> 
> > > > > result \>\>\>\>\>  
> > > > > “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”
> 
> > > > > end of example \>\>\>\>\>

Sorry, but it is a Ruby generated addiction…

Wolfgang NÃ¡dasi-Donner

---

<div class="post-metadata">

**Author:** ![lasastard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/58956e/32.png) [@lasastard](https://www.ruby-forum.com/u/lasastard)\
**Post date:** [July 22, 2007, 10:59am UTC](https://www.ruby-forum.com/t/line-split-with-some-complicating-factors/109919/7 "2007-07-22T10:59:57Z")

</div>

Wolfgang NÃ¡dasi-donner wrote:

> def put(a);(a = a.push(a.shift))[0];end

:oops: - overhead…

def put(a);a.push(a.shift)[0];end
