Problem populating a hash with regex results

R

RichardOnRails

Hi,

I've got a text file with 7 fields. I successfully extract the data
on each with a regex and for debugging purposes print each lines
fields.

Now I want to edit and organize the data for subsequent processing.
But populating the hash fails. I posted the code on http://www.pastie.org/1468271

The "puts" on line 15 shows that the regex captures the 7 fields in
the text file.
Lines 17-19 is an attempt to build a hash using the known values in
the $n variables.
That attempt fails because line 21 shows that it's nil instead the
string 100.0000 reported by line 15.

Maybe I should just build an array of the extracted values and use the
symbols I've created to index the array. In the mean time, mainly
for my education, I'd like to know where I went wrong with this hash.

Thanks in Advance,
Richard
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

On Sun, Jan 16, 2011 at 5:45 PM, RichardOnRails <
Hi,

I've got a text file with 7 fields. I successfully extract the data
on each with a regex and for debugging purposes print each lines
fields.

Now I want to edit and organize the data for subsequent processing.
But populating the hash fails. I posted the code on
http://www.pastie.org/1468271

The "puts" on line 15 shows that the regex captures the 7 fields in
the text file.
Lines 17-19 is an attempt to build a hash using the known values in
the $n variables.
That attempt fails because line 21 shows that it's nil instead the
string 100.0000 reported by line 15.

Maybe I should just build an array of the extracted values and use the
symbols I've created to index the array. In the mean time, mainly
for my education, I'd like to know where I went wrong with this hash.

Thanks in Advance,
Richard

Hi, Richard. It looks like your problem is that you put your data into your
hash with `:n_shares=>$2`, on line 17, but you pull it out with `puts
h[:shares]`, on line 21. When you get in weird situations like that, where
it seems correct on one line, and incorrect just a few later, give yourself
a sanity check by breaking it down into as small of steps as possible. I'd
think "well, if it isn't in there, then wtf does my hash look like?" and
instead of `puts h[:shares]` I'd stick a `p h` in there, which will print
out an inspected version of the array. At that point, I'd see the data
exists, and know the problem must be how I'm pulling it out.

Also, I don't think `h.each_pair { |n,v| h[n] = v }` does anything, you are
asking it for each key and value that it has, then telling it to set that
key to that value. Well, if it gave you that pair, then it is already set.
 
R

RichardOnRails

[Note:  parts of this message were removed to make it a legal post.]

I've got a text file with 7 fields.  I successfully extract the data
on each with a regex and for debugging purposes print each lines
fields.
Now I want to edit and organize the data for subsequent processing.
But populating the hash fails. I posted the code on
http://www.pastie.org/1468271
The "puts" on line 15 shows that the regex captures the 7 fields in
the text file.
Lines 17-19 is an attempt to build a hash using the known values in
the $n variables.
That attempt fails because line 21 shows that it's nil instead the
string 100.0000 reported by line 15.
Maybe I should just build an array of the extracted values and use the
symbols I've created to index the array.  In the mean time,  mainly
for my education, I'd like to know where I went wrong with this hash.
Thanks in Advance,
Richard

Hi, Richard. It looks like your problem is that you put your data into your
hash with `:n_shares=>$2`, on line 17, but you pull it out with `puts
h[:shares]`, on line 21. When you get in weird situations like that, where
it seems correct on one line, and incorrect just a few later, give yourself
a sanity check by breaking it down into as small of steps as possible. I'd
think "well, if it isn't in there, then wtf does my hash look like?" and
instead of `puts h[:shares]` I'd stick a `p h` in there, which will print
out an inspected version of the array. At that point, I'd see the data
exists, and know the problem must be how I'm pulling it out.

Also, I don't think `h.each_pair { |n,v| h[n] = v }` does anything, youare
asking it for each key and value that it has, then telling it to set that
key to that value. Well, if it gave you that pair, then it is already set..

Hi Josh,

Thanks for your reply. I wrote that stupid stuff late last night and
didn't like what I was composing. I wrote one approach for
initializing a hash and liked the result well enough, but didn't like
the copy & paste I did to create it. (I do as much cut and paste as I
can 'cause I hate to feel like a clerk-typist.)

So I had two redundant thing coded. And when I looked at it today, I
forgot what I was doing, so I sent out my SOS.
give yourself a sanity check by breaking it down into as small of steps as possible.

That's in keeping with Agile Programming's principle, and I'm
striving to embrace that. I'm gearing up to actually write my RSpec
stuff first before coding functionality.
I'd think "well, if it isn't in there, then wtf does my hash look like?" and instead of
`puts h[:shares]` I'd stick a `p h` in there.

That's a great point. I should wean myself off writing so much code
to inspect my code's result and use Ruby's inspect in the form of the
'p' command. Lesson learned, I hope.

This is my current idea for succinct code to support further data
analysis:

field_names =%w<Name Shares Opened_MDY Closed_MDY Proceeds Cost
GainLoss>
h = {}
(1..field_names.size).each { |name| h[name] = eval($ + i.to_s) }

Of course, that doesn't work, but despite my perusing of Pragmatic's
Programming Ruby, 2nd ed., I haven't so far figured out how to code
that third line. Any ideas. If you're too busy, or whatever, don't
bother responding and I'll post about it tomorrow.

Many thanks for your thoughtful help.

Best wishes,
Richard
 
R

RichardOnRails

[Note:  parts of this message were removed to make it a legal post.]
Hi,
I've got a text file with 7 fields.  I successfully extract the data
on each with a regex and for debugging purposes print each lines
fields.
Now I want to edit and organize the data for subsequent processing.
But populating the hash fails. I posted the code on
http://www.pastie.org/1468271
The "puts" on line 15 shows that the regex captures the 7 fields in
the text file.
Lines 17-19 is an attempt to build a hash using the known values in
the $n variables.
That attempt fails because line 21 shows that it's nil instead the
string 100.0000 reported by line 15.
Maybe I should just build an array of the extracted values and use the
symbols I've created to index the array.  In the mean time,  mainly
for my education, I'd like to know where I went wrong with this hash.
Thanks in Advance,
Richard
Hi, Richard. It looks like your problem is that you put your data into your
hash with `:n_shares=>$2`, on line 17, but you pull it out with `puts
h[:shares]`, on line 21. When you get in weird situations like that, where
it seems correct on one line, and incorrect just a few later, give yourself
a sanity check by breaking it down into as small of steps as possible. I'd
think "well, if it isn't in there, then wtf does my hash look like?" and
instead of `puts h[:shares]` I'd stick a `p h` in there, which will print
out an inspected version of the array. At that point, I'd see the data
exists, and know the problem must be how I'm pulling it out.
Also, I don't think `h.each_pair { |n,v| h[n] = v }` does anything, you are
asking it for each key and value that it has, then telling it to set that
key to that value. Well, if it gave you that pair, then it is already set.

Hi Josh,

Thanks for your reply.  I wrote that stupid stuff late last night and
didn't like what I was composing.  I wrote one approach for
initializing a hash and liked the result well enough, but didn't like
the copy & paste I did to create it.  (I do as much cut and paste as I
can 'cause I hate to feel like a clerk-typist.)

So I had two redundant thing coded.  And when I looked at it today,  I
forgot what I was doing, so I sent out my SOS.
give yourself a sanity check by breaking it down into as small of stepsas possible.

That's in keeping with Agile Programming's principle,  and I'm
striving to embrace that.  I'm gearing up to actually write my RSpec
stuff first before coding functionality.
I'd think "well, if it isn't in there, then wtf does my hash look like?" and instead of
`puts h[:shares]` I'd stick a `p h` in there.

That's a great point.  I should wean myself off writing so much code
to inspect my code's result and use Ruby's inspect in the form of the
'p' command.  Lesson learned, I hope.

This is my current idea for succinct code to support further data
analysis:

        field_names =%w<Name Shares Opened_MDY Closed_MDY Proceeds Cost
GainLoss>
        h = {}
        (1..field_names.size).each { |name| h[name] = eval($ + i.to_s) }

Of course, that doesn't work,  but despite my perusing of Pragmatic's
Programming Ruby, 2nd ed.,  I haven't so far figured out how to code
that third line.  Any ideas.  If you're too busy, or whatever,  don't
bother responding and I'll post about it tomorrow.

Many thanks for your thoughtful help.

Best wishes,
Richard

Hey Josh,

Please forget about this last question. It is garbled. I'm posting
it anew.

Thanks,
Richard
 
J

Jesús Gabriel y Galán

On Jan 16, 11:37=A0pm, RichardOnRails
This is my current idea for succinct code to support further data
analysis:

=A0 =A0 =A0 =A0 field_names =3D%w<Name Shares Opened_MDY Closed_MDY Proc= eeds Cost
GainLoss>
=A0 =A0 =A0 =A0 h =3D {}
=A0 =A0 =A0 =A0 (1..field_names.size).each { |name| h[name] =3D eval($ +=
i.to_s) }

I'd use a different approach. When you make the match, you can get an
array of the captured groups with:

md.captures

Then you can zip the two arrays together and use Hash#[] to create the hash=
:

For example:

irb(main):001:0> reg =3D /(.)(.)(.)(.)/
=3D> /(.)(.)(.)(.)/
irb(main):005:0> s =3D "1234"
=3D> "1234"
irb(main):007:0> field_names =3D %w{a b c d}
=3D> ["a", "b", "c", "d"]
irb(main):008:0> md =3D reg.match(s)
=3D> #<MatchData "1234" 1:"1" 2:"2" 3:"3" 4:"4">
irb(main):017:0> h =3D Hash[*field_names.zip(md.captures).flatten]
=3D> {"a"=3D>"1", "b"=3D>"2", "c"=3D>"3", "d"=3D>"4"}


Jesus.
 
R

Robert Klemme

This is my current idea for succinct code to support further data
analysis:

=A0 =A0 =A0 =A0field_names =3D%w<Name Shares Opened_MDY Closed_MDY Procee= ds Cost
GainLoss>
=A0 =A0 =A0 =A0h =3D {}
=A0 =A0 =A0 =A0(1..field_names.size).each { |name| h[name] =3D eval($ + i= to_s) }

Of course, that doesn't work, =A0but despite my perusing of Pragmatic's
Programming Ruby, 2nd ed., =A0I haven't so far figured out how to code
that third line. =A0Any ideas. =A0If you're too busy, or whatever, =A0don= 't
bother responding and I'll post about it tomorrow.

If you are on 1.9 there is a better approach: named capture groups.
These let you use your MatchData object like a Hash:

Ruby version 1.9.2
irb(main):001:0> rx =3D /(?'name'\w+)\s*=3D\s*(?'value'\S+)/
=3D> /(?'name'\w+)\s*=3D\s*(?'value'\S+)/
irb(main):002:0> md =3D rx.match " foo =3D 123 "
=3D> #<MatchData "foo =3D 123" name:"foo" value:"123">
irb(main):003:0> md[:name]
=3D> "foo"
irb(main):004:0> md[:value]
=3D> "123"
irb(main):005:0> md.names
=3D> ["name", "value"]
irb(main):006:0>

Note, there is an alternative syntax: (?<a name>rx)

See http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
R

RichardOnRails

This is my current idea for succinct code to support further data
analysis:
       field_names =%w<Name Shares Opened_MDY Closed_MDY Proceeds Cost
GainLoss>
       h = {}
       (1..field_names.size).each { |name| h[name] = eval($ +ito_s) }
Of course, that doesn't work,  but despite my perusing of Pragmatic's
Programming Ruby, 2nd ed.,  I haven't so far figured out how to code
that third line.  Any ideas.  If you're too busy, or whatever,  don't
bother responding and I'll post about it tomorrow.

If you are on 1.9 there is a better approach: named capture groups.
These let you use your MatchData object like a Hash:

Ruby version 1.9.2
irb(main):001:0> rx = /(?'name'\w+)\s*=\s*(?'value'\S+)/
=> /(?'name'\w+)\s*=\s*(?'value'\S+)/
irb(main):002:0> md = rx.match " foo = 123 "
=> #<MatchData "foo = 123" name:"foo" value:"123">
irb(main):003:0> md[:name]
=> "foo"
irb(main):004:0> md[:value]
=> "123"
irb(main):005:0> md.names
=> ["name", "value"]
irb(main):006:0>

Note, there is an alternative syntax: (?<a name>rx)

Seehttp://www.geocities.jp/kosako3/oniguruma/doc/RE.txt

Kind regards

robert

Hi Robert,

Thanks for your response. I didn't notice your reply because gave up
on this thread and restarted on
http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/6ddcea45d88ad810.

I'm still running 1.8.6 'cause it's worked well for me. Like the song
advises, "ya gotta dance with the guy that brung you." But I've copy
your advice to apply it after this project's done, at which time I'll
upgrade to 1.9.x.

Again, thanks,
Richars
 
R

Robert Klemme

This is my current idea for succinct code to support further data
analysis:
=A0 =A0 =A0 =A0field_names =3D%w<Name Shares Opened_MDY Closed_MDY Pro= ceeds Cost
GainLoss>
=A0 =A0 =A0 =A0h =3D {}
=A0 =A0 =A0 =A0(1..field_names.size).each { |name| h[name] =3D eval($ =
+ ito_s) }
Of course, that doesn't work, =A0but despite my perusing of Pragmatic'= s
Programming Ruby, 2nd ed., =A0I haven't so far figured out how to code
that third line. =A0Any ideas. =A0If you're too busy, or whatever, =A0= don't
bother responding and I'll post about it tomorrow.

If you are on 1.9 there is a better approach: named capture groups.
These let you use your MatchData object like a Hash:

Ruby version 1.9.2
irb(main):001:0> rx =3D /(?'name'\w+)\s*=3D\s*(?'value'\S+)/
=3D> /(?'name'\w+)\s*=3D\s*(?'value'\S+)/
irb(main):002:0> md =3D rx.match " foo =3D 123 "
=3D> #<MatchData "foo =3D 123" name:"foo" value:"123">
irb(main):003:0> md[:name]
=3D> "foo"
irb(main):004:0> md[:value]
=3D> "123"
irb(main):005:0> md.names
=3D> ["name", "value"]
irb(main):006:0>

Note, there is an alternative syntax: (?<a name>rx)

Seehttp://www.geocities.jp/kosako3/oniguruma/doc/RE.txt

Kind regards

robert
practices.com/

Hi Robert,

Thanks for your response. =A0I didn't notice your reply because gave up
on this thread and restarted on
http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/6ddcea= 45d88ad810.

I'm still running 1.8.6 'cause it's worked well for me. =A0Like the song
advises, "ya gotta dance with the guy that brung you." =A0But I've copy
your advice to apply it after this project's done, at which time I'll
upgrade to 1.9.x.

Well, let's see what we can do...

irb(main):001:0> MDWrap =3D Struct.new :md, :fields do
irb(main):002:1* def [](name) md[fields[name]] end
irb(main):003:1> end
=3D> MDWrap
irb(main):004:0> md =3D MDWrap.new("foobar".match(/(fo+)(ba\w+)/),
:name=3D>1,:value=3D>2)
=3D> #<struct MDWrap md=3D#<MatchData "foobar" 1:"foo" 2:"bar">,
fields=3D{:value=3D>2, :name=3D>1}>
irb(main):005:0> md[:name]
=3D> "foo"

or

irb(main):007:0> names =3D {:name =3D> 1, :value =3D> 2}
=3D> {:value=3D>2, :name=3D>1}
irb(main):008:0> md =3D "foobar".match(/(fo+)(ba\w+)/)
=3D> #<MatchData "foobar" 1:"foo" 2:"bar">
irb(main):009:0> md[names[:name]]
=3D> "foo"

Or you use indexes directly.

:)

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top