# External to internal conversion

**URL:** <https://rubytalk.org/t/external-to-internal-conversion/34507>\
**Category:** ruby-talk\
**Created:** [16 January 2007 15:17 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507 "2007-01-16T15:17:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Peter\_L\_Versteegen](https://avatars.discourse-cdn.com/v4/letter/p/dbc845/32.png) [@Peter\_L\_Versteegen](https://rubytalk.org/u/Peter_L_Versteegen)\
**Post date:** [16 January 2007 15:17 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/1 "2007-01-16T15:17:08Z")

</div>

Hi,

I have been following this list off and on but have not found the  
solution to my problem. I want to convert data supplied by a file into  
their corresponding internal values.

I have an external file with data that are in the form "variable name",  
tab, followed by their value. The 'value 'can be a single number, an  
array of numbers, or a matrix of numbers, For example, the file might  
look like this:  
a 2.4  
b 1,0, 3.0, 5.0  
c 5, 6, 11  
d [1, 2], [5, 6], [45,55]  
e 2\*[7, 8]

I can get a, b, and c to convert to single values and arrays, thanks to  
this forum, but I cannot figure out a way to convert d into an array of  
arrays. I haven't taclked e yet. Does anyone have any suggestions?

Ideally I would like to match the variable name in the file to the  
corresponding and same name already coded in the program. Any ideas how  
to do that?

Thanks

Pete Versteegen

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

---

<div class="post-metadata">

**Author:** ![Peter\_L\_Versteegen](https://avatars.discourse-cdn.com/v4/letter/p/dbc845/32.png) [@Peter\_L\_Versteegen](https://rubytalk.org/u/Peter_L_Versteegen)\
**Post date:** [16 January 2007 18:46 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/2 "2007-01-16T18:46:01Z")

</div>

Hello All,

I like to rephrase my problem below by the following interactive  
session:

> > x = "1, 12, 500"

=\> "1, 12, 500"

> > a = x.split(",").map {|k| k.to\_i}

=\> [1, 12, 500]

> > y = "[25.0, 26], [30, 31]"

=\> "[25.0, 26], [30, 31]"

> > b = y.split(",").map {|k| k.to\_i}

=\> [0, 26, 0, 31]

I get what I want in the 4th line, an array of numbers  
I don't get, nor did I expect to, what I want in the last line, i.e., an  
array of arrays.  
How can I convert to an array of arrays?

Thanks,

Peter Versteegen wrote:

> **···**
>
> > Hi,
> > 
> > I have been following this list off and on but have not found the  
> > solution to my problem. I want to convert data supplied by a file into  
> > their corresponding internal values.
> > 
> > I have an external file with data that are in the form "variable name",  
> > tab, followed by their value. The 'value 'can be a single number, an  
> > array of numbers, or a matrix of numbers, For example, the file might  
> > look like this:  
> > a 2.4  
> > b 1,0, 3.0, 5.0  
> > c 5, 6, 11  
> > d [1, 2], [5, 6], [45,55]  
> > e 2\*[7, 8]
> > 
> > I can get a, b, and c to convert to single values and arrays, thanks to  
> > this forum, but I cannot figure out a way to convert d into an array of  
> > arrays. I haven't taclked e yet. Does anyone have any suggestions?
> > 
> > Ideally I would like to match the variable name in the file to the  
> > corresponding and same name already coded in the program. Any ideas how  
> > to do that?
> > 
> > Thanks
> > 
> > Pete Versteegen
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Wilson\_Bilkovich](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/wilson_bilkovich/32/8247_2.png) [@Wilson\_Bilkovich](https://rubytalk.org/u/Wilson_Bilkovich)\
**Post date:** [16 January 2007 18:51 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/3 "2007-01-16T18:51:13Z")

</div>

> Hello All,
> 
> I like to rephrase my problem below by the following interactive  
> session:  
> \>\> x = "1, 12, 500"  
> =\> "1, 12, 500"  
> \>\> a = x.split(",").map {|k| k.to\_i}  
> =\> [1, 12, 500]  
> \>\> y = "[25.0, 26], [30, 31]"  
> =\> "[25.0, 26], [30, 31]"  
> \>\> b = y.split(",").map {|k| k.to\_i}  
> =\> [0, 26, 0, 31]
> 
> I get what I want in the 4th line, an array of numbers  
> I don't get, nor did I expect to, what I want in the last line, i.e., an  
> array of arrays.  
> How can I convert to an array of arrays?
> 
> > input = "[25.0, 26], [30, 31]"

=\> "[25.0, 26], [30, 31]"

> > input.scan(/\d+\.?\d\*/)

=\> ["25.0", "26", "30", "31"]

Something like that?

> **···**
>
> On 1/16/07, Peter Versteegen \<pversteegen@gcnetmail.net\> wrote:

---

<div class="post-metadata">

**Author:** ![Jim\_Lindley1](https://avatars.discourse-cdn.com/v4/letter/j/c4cdca/32.png) [@Jim\_Lindley1](https://rubytalk.org/u/Jim_Lindley1)\
**Post date:** [16 January 2007 22:04 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/4 "2007-01-16T22:04:48Z")

</div>

If your data really is in that format, you can add an extra set of  
brackets around the whole thing to read it in as an array literal.  
Just be sure that the data source is trustworthy and you if you're  
going to eval it! If you aren't generating or strongly filtering the  
inputs this is probably a bad idea.

> input = "[25.0, 26], [30, 31]"

=\> "[25.0, 26], [30, 31]"

> input = "[" + input + "]"

=\> "[[25.0, 26], [30, 31]]"

> eval input

=\> [[25.0, 26], [30, 31]]

> result = eval input

=\> [[25.0, 26], [30, 31]]

> result[0][1]

=\> 26

But maybe you were just simplifying the input data format to present  
the problem?

---

<div class="post-metadata">

**Author:** ![Peter\_L\_Versteegen](https://avatars.discourse-cdn.com/v4/letter/p/dbc845/32.png) [@Peter\_L\_Versteegen](https://rubytalk.org/u/Peter_L_Versteegen)\
**Post date:** [16 January 2007 20:28 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/5 "2007-01-16T20:28:16Z")

</div>

Wilson,

I was looking more for an output like [[25.0, 26], [30, 31]], an aray of two arrays.

Thanks,

Pete Versteegen

> **···**
>
> On Jan 16, 2007, at 1:51 PM, Wilson Bilkovich wrote:
> 
> > On 1/16/07, Peter Versteegen \<pversteegen@gcnetmail.net\> wrote:
> > 
> > > Hello All,
> > > 
> > > I like to rephrase my problem below by the following interactive  
> > > session:  
> > > \>\> x = "1, 12, 500"  
> > > =\> "1, 12, 500"  
> > > \>\> a = x.split(",").map {|k| k.to\_i}  
> > > =\> [1, 12, 500]  
> > > \>\> y = "[25.0, 26], [30, 31]"  
> > > =\> "[25.0, 26], [30, 31]"  
> > > \>\> b = y.split(",").map {|k| k.to\_i}  
> > > =\> [0, 26, 0, 31]
> > > 
> > > I get what I want in the 4th line, an array of numbers  
> > > I don't get, nor did I expect to, what I want in the last line, i.e., an  
> > > array of arrays.  
> > > How can I convert to an array of arrays?
> > > 
> > > > input = "[25.0, 26], [30, 31]"
> > 
> > =\> "[25.0, 26], [30, 31]"
> > 
> > > > input.scan(/\d+\.?\d\*/)
> > 
> > =\> ["25.0", "26", "30", "31"]
> > 
> > Something like that?

---

<div class="post-metadata">

**Author:** ![Peter\_L\_Versteegen](https://avatars.discourse-cdn.com/v4/letter/p/dbc845/32.png) [@Peter\_L\_Versteegen](https://rubytalk.org/u/Peter_L_Versteegen)\
**Post date:** [16 January 2007 23:21 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/6 "2007-01-16T23:21:54Z")

</div>

Thanks Jim for another approach.

I saw the use of "eval" in Jim Fulton's "The Ruby Way" but didn't quite  
understand it. I do plan to filter the data to make sure that the  
numbers are there and the format is consistent.

The input data format is a natural and easy way to specify the problem  
I'm trying to solve, so I'll keep the format but do the evaluation  
inside the code.

Thanks again.

Pete Versteegen

Jim Lindley wrote:

> **···**
>
> > If your data really is in that format, you can add an extra set of  
> > brackets around the whole thing to read it in as an array literal.  
> > Just be sure that the data source is trustworthy and you if you're  
> > going to eval it! If you aren't generating or strongly filtering the  
> > inputs this is probably a bad idea.
> > 
> > \> input = "[25.0, 26], [30, 31]"  
> > =\> "[25.0, 26], [30, 31]"  
> > \> input = "[" + input + "]"  
> > =\> "[[25.0, 26], [30, 31]]"  
> > \> eval input  
> > =\> [[25.0, 26], [30, 31]]  
> > \> result = eval input  
> > =\> [[25.0, 26], [30, 31]]  
> > \> result[0][1]  
> > =\> 26
> > 
> > But maybe you were just simplifying the input data format to present  
> > the problem?
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Wilson\_Bilkovich](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/wilson_bilkovich/32/8247_2.png) [@Wilson\_Bilkovich](https://rubytalk.org/u/Wilson_Bilkovich)\
**Post date:** [16 January 2007 20:50 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/7 "2007-01-16T20:50:03Z")

</div>

> Wilson,
> 
> I was looking more for an output like [[25.0, 26], [30, 31]], an aray  
> of two arrays.
> 
> Thanks,

Probably easiest to do it in two steps, since bracket-matching is a  
real chore in a regular expression.

> > input = "[25.0, 26], [30, 31]"

=\> "[25.0, 26], [30, 31]"

> > groups = input.scan(/\[.\*?\]/)

=\> ["[25.0, 26]", "[30, 31]"]

> > output = groups.map {|g| g.scan(/\d+\.?\d\*/).map {|n| n.to\_i} }

=\> [[25, 26], [30, 31]]

Do you really need 25.0 instead of 25? Mixing integers and floats can  
be a bad idea. Adjust the 'to\_i' call accordingly.

> **···**
>
> On 1/16/07, Peter Versteegen \<pversteegen@gcnetmail.net\> wrote:

---

<div class="post-metadata">

**Author:** ![Peter\_L\_Versteegen](https://avatars.discourse-cdn.com/v4/letter/p/dbc845/32.png) [@Peter\_L\_Versteegen](https://rubytalk.org/u/Peter_L_Versteegen)\
**Post date:** [16 January 2007 23:03 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/8 "2007-01-16T23:03:48Z")

</div>

Thanks Wilson,

That did it for me. I know not to mix integers and floats; that was a  
typing error. I know very little about regular expressions. Could you  
put in words what you did?

Thanks again.

Wilson Bilkovich wrote:

> **···**
>
> > On 1/16/07, Peter Versteegen \<pversteegen@gcnetmail.net\> wrote:
> > 
> > > Wilson,
> > > 
> > > I was looking more for an output like [[25.0, 26], [30, 31]], an aray  
> > > of two arrays.
> > > 
> > > Thanks,
> > 
> > Probably easiest to do it in two steps, since bracket-matching is a  
> > real chore in a regular expression.
> > 
> > > > input = "[25.0, 26], [30, 31]"
> > 
> > =\> "[25.0, 26], [30, 31]"
> > 
> > > > groups = input.scan(/\[.\*?\]/)
> > 
> > =\> ["[25.0, 26]", "[30, 31]"]
> > 
> > > > output = groups.map {|g| g.scan(/\d+\.?\d\*/).map {|n| n.to\_i} }
> > 
> > =\> [[25, 26], [30, 31]]
> > 
> > Do you really need 25.0 instead of 25? Mixing integers and floats can  
> > be a bad idea. Adjust the 'to\_i' call accordingly.
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Wilson\_Bilkovich](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/wilson_bilkovich/32/8247_2.png) [@Wilson\_Bilkovich](https://rubytalk.org/u/Wilson_Bilkovich)\
**Post date:** [17 January 2007 05:15 UTC](https://rubytalk.org/t/external-to-internal-conversion/34507/9 "2007-01-17T05:15:25Z")

</div>

> Thanks Wilson,
> 
> That did it for me. I know not to mix integers and floats; that was a  
> typing error. I know very little about regular expressions. Could you  
> put in words what you did?

Sure.

> > groups = input.scan(/\[.\*?\]/)

The forward slashes just delimit the regular expression  
[and] are characters with special meaning in regexps; they create  
'character classes'. [a-z] means, for example, every lowercase letter  
The backslashes escape them, because we mean literal brackets

.\* means 'any character at all, zero or more times'  
The ? after it means, 'match that as FEW times as possible'.  
Without that, we would get everything up to the last ], when what we  
want is everything up to the NEXT ].

Together that expression means 'an opening bracket, anything  
(or nothing), and then a closing bracket'

Next we take the array of strings we just built, and hand scan it again.  
This time, the pattern is: \d+\.?\d\*  
\d means "a digit", and is shorthand for [0-9], which would be the  
class of all digits, 0 to 9.  
+ after an expression means '1 or more times'. (Note the difference  
between this and \*, which means 0 or more.)  
'.' is a reserved character meaning 'any single character', so we  
again escape it here with a backslash.  
\.? means 'a period, zero or one times'  
Finally, we have: \d\*, which means 'zero or more consecutive digits'

Combined, \d+\.?\d\* means 'a series of digits, optionally followed by  
a decimal point and more digits'. Arguably that pattern needs to be  
enhanced, because at the moment it would match "25."  
You only get so much from a free email, though. Heh

To sum up; first scan for "[stuff]" and then scan the contents of  
those for things that look like numbers.

> **···**
>
> On 1/16/07, Peter Versteegen \<pversteegen@gcnetmail.net\> wrote:
