# Split the string

**URL:** <https://rubytalk.org/t/split-the-string/44915>\
**Category:** ruby-talk\
**Created:** [3 March 2008 05:31 UTC](https://rubytalk.org/t/split-the-string/44915 "2008-03-03T05:31:43Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sijo\_Kg](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sijo\_Kg](https://rubytalk.org/u/Sijo_Kg)\
**Post date:** [3 March 2008 05:31 UTC](https://rubytalk.org/t/split-the-string/44915/1 "2008-03-03T05:31:43Z")

</div>

I have a string  
@selected\_related\_model\_id\_assotype\_and\_name=params[:relatedidmodelasso]

This is of the form  
3:43;SD,2:65;SD,3:50;Inc

How can i split this to get

=\>[["3","43","SD"],["2","65","SD"],["3","50","Inc"]]

Sijo

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Christopher\_Swasey](https://avatars.discourse-cdn.com/v4/letter/c/cab0a1/32.png) [@Christopher\_Swasey](https://rubytalk.org/u/Christopher_Swasey)\
**Post date:** [3 March 2008 05:42 UTC](https://rubytalk.org/t/split-the-string/44915/2 "2008-03-03T05:42:25Z")

</div>

First split by the comma, then #map the result and split using a conditional:

"3:43;SD,2:65;SD,3:50;Inc".split(/,/).map { |i| i.split(/:|;/) }  
=\> [["3", "43", "SD"], ["2", "65", "SD"], ["3", "50", "Inc"]]

Christopher

> **···**
>
> On 3/3/08, Sijo Kg \<sijo@maxxion.com\> wrote:
> 
> > I have a string  
> > @selected\_related\_model\_id\_assotype\_and\_name=params[:relatedidmodelasso]
> > 
> > This is of the form  
> > 3:43;SD,2:65;SD,3:50;Inc
> > 
> > How can i split this to get
> > 
> > =\>[["3","43","SD"],["2","65","SD"],["3","50","Inc"]]
> > 
> > Sijo

---

<div class="post-metadata">

**Author:** ![\_Pena\_Botp1](https://avatars.discourse-cdn.com/v4/letter/_/94ad74/32.png) [@\_Pena\_Botp1](https://rubytalk.org/u/_Pena_Botp1)\
**Post date:** [3 March 2008 07:19 UTC](https://rubytalk.org/t/split-the-string/44915/3 "2008-03-03T07:19:34Z")

</div>

On Behalf Of Sijo Kg:  
# This is of the form  
# 3:43;SD,2:65;SD,3:50;Inc  
# How can i split this to get  
# =\>[["3","43","SD"],["2","65","SD"],["3","50","Inc"]]  
#...  
# Here i have to get the first 2 fields as integer and the third as  
# string

read on split, arrays, and enumerators.

this is just a simple example,

irb(main):037:0\> require 'enumerator'  
=\> false

irb(main):038:0\> s="3:43;SD,2:65;SD,3:50;Inc" =\> "3:43;SD,2:65;SD,3:50;Inc"

irb(main):039:0\> a=[]  
=\> []

irb(main):040:0\> s.split(/,|:|;/).each\_slice(3){|x| a \<\< [x[0].to\_i,x[1].to\_i,x[2]]}  
=\> nil

irb(main):041:0\> a  
=\> [[3, 43, "SD"], [2, 65, "SD"], [3, 50, "Inc"]]

kind regards -botp

---

<div class="post-metadata">

**Author:** ![Michael\_Fellinger1](https://avatars.discourse-cdn.com/v4/letter/m/e47774/32.png) [@Michael\_Fellinger1](https://rubytalk.org/u/Michael_Fellinger1)\
**Post date:** [3 March 2008 08:02 UTC](https://rubytalk.org/t/split-the-string/44915/4 "2008-03-03T08:02:00Z")

</div>

require 'scanf'  
"3:43;SD,2:65;SD,3:50;Inc".split(',').map do |e|  
&nbsp;&nbsp;e.scanf('%d:%d;%s')  
end  
# [[3, 43, "SD"], [2, 65, "SD"], [3, 50, "Inc"]]

^ manveru

> **···**
>
> On Mon, Mar 3, 2008 at 2:31 PM, Sijo Kg \<sijo@maxxion.com\> wrote:
> 
> > I have a string  
> > @selected\_related\_model\_id\_assotype\_and\_name=params[:relatedidmodelasso]
> > 
> > This is of the form  
> > 3:43;SD,2:65;SD,3:50;Inc
> > 
> > How can i split this to get
> > 
> > =\>[["3","43","SD"],["2","65","SD"],["3","50","Inc"]]

---

<div class="post-metadata">

**Author:** ![suprabha\_r](https://avatars.discourse-cdn.com/v4/letter/s/eb9ed0/32.png) [@suprabha\_r](https://rubytalk.org/u/suprabha_r)\
**Post date:** [18 July 2011 07:13 UTC](https://rubytalk.org/t/split-the-string/44915/5 "2011-07-18T07:13:19Z")

</div>

hi  
its a simple question yet google wasnt of much help

string = a\_b\_c\_d\_e

search results mostly show how to split it as a b c d e

but how to split it as a\_b and c\_d\_e ?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Sijo\_Kg](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sijo\_Kg](https://rubytalk.org/u/Sijo_Kg)\
**Post date:** [3 March 2008 05:51 UTC](https://rubytalk.org/t/split-the-string/44915/6 "2008-03-03T05:51:47Z")

</div>

Thanks for your reply

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Sijo\_Kg](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sijo\_Kg](https://rubytalk.org/u/Sijo_Kg)\
**Post date:** [3 March 2008 06:05 UTC](https://rubytalk.org/t/split-the-string/44915/7 "2008-03-03T06:05:41Z")

</div>

Sir

Here i have to get the first 2 fields as integer and the third as  
string.Could u please tell how can i do that in the map?

Sijo

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Christopher\_Swasey](https://avatars.discourse-cdn.com/v4/letter/c/cab0a1/32.png) [@Christopher\_Swasey](https://rubytalk.org/u/Christopher_Swasey)\
**Post date:** [3 March 2008 08:15 UTC](https://rubytalk.org/t/split-the-string/44915/8 "2008-03-03T08:15:54Z")

</div>

We have a winner!

Christopher

> **···**
>
> On 3/3/08, Michael Fellinger \<m.fellinger@gmail.com\> wrote:
> 
> > On Mon, Mar 3, 2008 at 2:31 PM, Sijo Kg \<sijo@maxxion.com\> wrote:  
> > \> I have a string  
> > \> @selected\_related\_model\_id\_assotype\_and\_name=params[:relatedidmodelasso]  
> > \>  
> > \> This is of the form  
> > \> 3:43;SD,2:65;SD,3:50;Inc  
> > \>  
> > \> How can i split this to get  
> > \>  
> > \> =\>[["3","43","SD"],["2","65","SD"],["3","50","Inc"]]
> > 
> > require 'scanf'  
> > "3:43;SD,2:65;SD,3:50;Inc".split(',').map do |e|  
> > &nbsp;&nbsp;e.scanf('%d:%d;%s')  
> > end  
> > # [[3, 43, "SD"], [2, 65, "SD"], [3, 50, "Inc"]]
> > 
> > ^ manveru

---

<div class="post-metadata">

**Author:** ![\_Pena\_Botp1](https://avatars.discourse-cdn.com/v4/letter/_/94ad74/32.png) [@\_Pena\_Botp1](https://rubytalk.org/u/_Pena_Botp1)\
**Post date:** [4 March 2008 03:01 UTC](https://rubytalk.org/t/split-the-string/44915/9 "2008-03-04T03:01:49Z")

</div>

# Michael Fellinger wrote:  
# \> require 'scanf'  
# \> "3:43;SD,2:65;SD,3:50;Inc".split(',').map do |e|  
# \> e.scanf('%d:%d;%s')  
# \> end  
# \> # [[3, 43, "SD"], [2, 65, "SD"], [3, 50, "Inc"]]

> **···**
>
> From: S2 [[mailto:non.sto.gioando@nien.te](mailto:non.sto.gioando@nien.te)]  
> #  
> # but he wants all strings in his array
> 
> no, if you scan the thread, the op later wanted the first 2 elements be integers.
> 
> kind regards -botp

---

<div class="post-metadata">

**Author:** ![Ryan\_Davis1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/ryan_davis1/32/1848_2.png) [@Ryan\_Davis1](https://rubytalk.org/u/Ryan_Davis1)\
**Post date:** [18 July 2011 07:29 UTC](https://rubytalk.org/t/split-the-string/44915/10 "2011-07-18T07:29:21Z")

</div>

Your question is too arbitrary. What criteria are you hoping to split it by? Index? Content? Randomly? I can come up with many answers to your question, but that doesn't mean it is the right answer.

Have you looked directly at the documentation for String? Try typing `ri String` and then maybe `ri String#index` into your terminal.

> **···**
>
> On Jul 18, 2011, at 00:13 , suprabha r. wrote:
> 
> > hi  
> > its a simple question yet google wasnt of much help
> > 
> > string = a\_b\_c\_d\_e
> > 
> > search results mostly show how to split it as a b c d e
> > 
> > but how to split it as a\_b and c\_d\_e ?

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [18 July 2011 08:36 UTC](https://rubytalk.org/t/split-the-string/44915/11 "2011-07-18T08:36:42Z")

</div>

suprabha r. wrote in post #1011335:

> hi  
> its a simple question yet google wasnt of much help
> 
> string = a\_b\_c\_d\_e
> 
> search results mostly show how to split it as a b c d e
> 
> but how to split it as a\_b and c\_d\_e ?

Well, one obvious way is to split it into ["a","b","c","d","e"] as  
google showed, select the bits you want, then join them back together  
again. Look at Array#join.

&nbsp;&nbsp;&nbsp;&nbsp;["a","b"].join("\_") # =\> "a\_b"

Another way is to use a regular expression to match the patterns you're  
looking for. e.g.

&nbsp;&nbsp;&nbsp;&nbsp;if string =~ /\A([^\_]\*\_[^\_]\*)\_(.\*)\z/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str1, str2 = $1, $2  
&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise "Unexpected format"  
&nbsp;&nbsp;&nbsp;&nbsp;end

There are many resources on ruby regular expressions you can google for.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Christopher\_Swasey](https://avatars.discourse-cdn.com/v4/letter/c/cab0a1/32.png) [@Christopher\_Swasey](https://rubytalk.org/u/Christopher_Swasey)\
**Post date:** [3 March 2008 06:37 UTC](https://rubytalk.org/t/split-the-string/44915/12 "2008-03-03T06:37:37Z")

</div>

Not so elegantly.

Map doesn't come in handy here because the string would get converted  
to a 0. What you can do is hold the split inside a temporary variable  
and construct another array, as such:

arr = "3:43;SD,2:65;SD,3:50;Inc".split(/,/).map do |i|  
&nbsp;&nbsp;t = i.split(/:|;/)  
&nbsp;&nbsp;t[0..1].map { |j| j.to\_i } \<\< t[2]

&nbsp;&nbsp;### If you're using Rails you can use Symbol#to\_proc to simplify the code  
&nbsp;&nbsp;# t[0..1].map(&:to\_i) \<\< t[2]

&nbsp;&nbsp;### or something very simple, if a tiny bit repetitive:  
&nbsp;&nbsp;# [t[0].to\_i, t[1].to\_i, t[2]]  
end  
=\> [[3, 43, "SD"], [2, 65, "SD"], [3, 50, "Inc"]]

Christopher

> **···**
>
> On 3/3/08, Sijo Kg \<sijo@maxxion.com\> wrote:
> 
> > Sir
> > 
> > &nbsp;&nbsp;Here i have to get the first 2 fields as integer and the third as  
> > string.Could u please tell how can i do that in the map?

---

<div class="post-metadata">

**Author:** ![\_Pena\_Botp1](https://avatars.discourse-cdn.com/v4/letter/_/94ad74/32.png) [@\_Pena\_Botp1](https://rubytalk.org/u/_Pena_Botp1)\
**Post date:** [4 March 2008 03:06 UTC](https://rubytalk.org/t/split-the-string/44915/13 "2008-03-04T03:06:18Z")

</div>

# \> require 'scanf'  
# \> "3:43;SD,2:65;SD,3:50;Inc".split(',').map do |e|  
# \> e.scanf('%d:%d;%s')  
# \> end  
# \> # [[3, 43, "SD"], [2, 65, "SD"], [3, 50, "Inc"]]  
# \>  
# \> ^ manveru

> **···**
>
> From: Christopher Swasey [[mailto:christopher.swasey@gmail.com](mailto:christopher.swasey@gmail.com)]  
> # On 3/3/08, Michael Fellinger \<[m.fellinger@gmail.com](mailto:m.fellinger@gmail.com)\> wrote:  
> #  
> # We have a winner!  
> #
> 
> careful, you might want to benchmark that, too.
> 
> a sample run on a windows machine,
> 
> C:\Documents and Settings\botp\>cat test.rb
> 
> require 'benchmark'  
> require 'enumerator'  
> require 'scanf'
> 
> n=1\_000  
> s="3:43;SD,2:65;SD,3:50;Inc"
> 
> puts RUBY\_VERSION,RUBY\_PLATFORM
> 
> Benchmark.bmbm do |x|  
> &nbsp;&nbsp;x.report("scan") do  
> &nbsp;&nbsp;&nbsp;&nbsp;n.times do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.scan(/(\d+):(\d+);(\w+)/).map do |x| [x[0].to\_i,x[1].to\_i,x[2]] e  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> &nbsp;&nbsp;x.report("slice") do  
> &nbsp;&nbsp;&nbsp;&nbsp;n.times do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a=[]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.split(/,|:|;/).each\_slice(3){|x| a \<\< [x[0].to\_i,x[1].to\_i,x[2]]}  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> &nbsp;&nbsp;x.report("split2") do  
> &nbsp;&nbsp;&nbsp;&nbsp;n.times do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.split(/,/).map do |i|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = i.split(/:|;/)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[0..1].map { |j| j.to\_i } \<\< t[2]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> &nbsp;&nbsp;x.report("scanf") do  
> &nbsp;&nbsp;&nbsp;&nbsp;n.times do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.split(',').map do |e| e.scanf('%d:%d;%s') end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> end
> 
> C:\Documents and Settings\peñaijm\>ruby test.rb  
> 1.8.6  
> i386-mswin32  
> Rehearsal ------------------------------------------  
> scan 0.063000 0.000000 0.063000 ( 0.063000)  
> slice 0.078000 0.000000 0.078000 ( 0.079000)  
> split2 0.109000 0.000000 0.109000 ( 0.110000)  
> scanf 2.938000 0.015000 2.953000 ( 3.188000)  
> --------------------------------- total: 3.203000sec
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
> scan 0.063000 0.000000 0.063000 ( 0.063000)  
> slice 0.093000 0.000000 0.093000 ( 0.094000)  
> split2 0.125000 0.000000 0.125000 ( 0.125000)  
> scanf 2.984000 0.032000 3.016000 ( 3.031000)
> 
> kind regards -botp

---

<div class="post-metadata">

**Author:** ![Sijo\_Kg](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sijo\_Kg](https://rubytalk.org/u/Sijo_Kg)\
**Post date:** [3 March 2008 06:49 UTC](https://rubytalk.org/t/split-the-string/44915/14 "2008-03-03T06:49:17Z")

</div>

Here what is the meaning of this

t[0..1].map(&:to\_i) \<\< t[2]

Could u please explain details what split and map does?I am beginner in  
ruby and ror

Sijo

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Christopher\_Swasey](https://avatars.discourse-cdn.com/v4/letter/c/cab0a1/32.png) [@Christopher\_Swasey](https://rubytalk.org/u/Christopher_Swasey)\
**Post date:** [3 March 2008 07:20 UTC](https://rubytalk.org/t/split-the-string/44915/15 "2008-03-03T07:20:51Z")

</div>

The code, for reference:

arr = "3:43;SD,2:65;SD,3:50;Inc".split(/,/).map do |i|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = i.split(/:|;/)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[0..1].map(&:to\_i) \<\< t[2]  
end

First, what we're doing here is splitting the string into an array by  
the commas. This gets us  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=\> ["3:43;SD", "2:65;SD", "3:50;Inc"]

Then we're iterating through the resulting array using #map. #map is  
provided by Enumerable. It iterates through all the elements of a  
collection and combines the results into a new array.

#map passes each element to a block, one at a time. So, the first  
element that gets passsed to the block is the string "3:43;SD". What's  
important about the block is that the last expression to be evaluated  
gets returned, and #map will add the returned value onto the array  
that it's building. Inside the block we can do whatever we need to to  
build the returned value.

In this case, we want the returned value to be a second array with the  
individual parts of the current string split up. If it didn't matter  
whether or not the resulting values were strings or integers then we  
could just call #split on the string and leave it at that, as  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"3:43;SD".split(/:\;/)  
returns  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=\> ["3", "43", "SD"]  
which, as the last expression evaluated, would get returned by the  
block and pushed onto the array being built by #map.

You can think of #map as a function that transforms a collection, item  
by item, and gives you back a new collection of the same size with the  
same transformation applied to each constituent element. In this case,  
we're taking an array of strings, transforming each individual string  
into its own array, and we end up with an array of arrays.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=\> [["3", "43", "SD"], ["2", "65", "SD"], ["3", "50", "Inc"]]

Now, in this case all we've done is split a bunch of strings, so each  
ultimate element of the array is still going to be a string, even when  
they appear to be numbers and we want them to be integers. Ideally,  
what we'd do is a nested #map that called #to\_i on each element to  
convert them to integers:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i.split(/:|;/).map { |j| j.to\_i }  
The problem is that we want the third element to remain a string.  
Calling #to\_i on "SD" will return  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=\> 0

Which brings us to  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[0..1].map(&:to\_i) \<\< t[2]

What this does is slice out the first two elements of the array that  
the #split gave us. This results in an array. In this case t[0..1]  
would give us  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=\> ["3", "43"]

Then we're mapping that to a new array by calling to\_i on each element  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=\> [3, 43]

Finally, we're pushing the string that we want to keep ("SD") onto the end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3, 43] \<\< t[2]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=\> [3, 43, "SD"]

As the last expression to be evaluated, that completed array is  
returned to #map and gets pushed onto the final, resulting array.

Now, I kind of skipped over a bit of code.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[0..1].map(&:to\_i) \<\< t[2]  
Specifically, the "&:to\_i" part. This is somewhat advanced, and I'd  
suggest that you read up on blocks and Procs ASAP. This is a good  
opportunity to do so. Such knowledge is a prerequisite to  
understanding Symbol#to\_proc. (Symbol#to\_proc, btw, isn't part of Ruby  
core, it's a feature of Rails, although not exclusively).

To put it in simple terms, prepending & to a symbol results in  
#to\_proc being called on that symbol. #to\_proc returns a simple block  
which accepts an object and calls the specified method. In this case,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.map(&:to\_i)  
is the equivalent of  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.map { |i| i.to\_i }

Again, it's very simple and neat and efficient if you understand how  
all the pieces of Ruby link together to make it possible. Once you  
read up on Procs and blocks it should make sense.

Christopher

> **···**
>
> On 3/3/08, Sijo Kg \<sijo@maxxion.com\> wrote:
> 
> > Here what is the meaning of this
> > 
> > t[0..1].map(&:to\_i) \<\< t[2]
> > 
> > Could u please explain details what split and map does?I am beginner in  
> > ruby and ror
