Problem populating a hash with regex results

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

On Sun, Jan 16, 2011 at 5:45 PM, RichardOnRails <
[email protected]> wrote:

The “puts” on line 15 shows that the regex captures the 7 fields in
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.

On Jan 16, 7:06pm, Josh C. [email protected] wrote:

on each with a regex and for debugging purposes print each lines
That attempt fails because line 21 shows that it’s nil instead the
hash with :n_shares=>$2, on line 17, but you pull it out with `puts
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
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

On Jan 16, 11:37pm, RichardOnRails
[email protected] wrote:

Lines 17-19 is an attempt to build a hash using the known values in

Also, I don’t think h.each_pair { |n,v| h[n] = v } does anything, you are

puts h[:shares] I’d stick a p h in there.
h = {}
Richard
Hey Josh,

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

Thanks,
Richard

On Mon, Jan 17, 2011 at 6:05 AM, RichardOnRails
[email protected] wrote:

On Jan 16, 11:37pm, 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($ + 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 = /(.)(.)(.)(.)/
=> /(.)(.)(.)(.)/
irb(main):005:0> s = “1234”
=> “1234”
irb(main):007:0> field_names = %w{a b c d}
=> [“a”, “b”, “c”, “d”]
irb(main):008:0> md = reg.match(s)
=> #<MatchData “1234” 1:“1” 2:“2” 3:“3” 4:“4”>
irb(main):017:0> h = Hash[*field_names.zip(md.captures).flatten]
=> {“a”=>“1”, “b”=>“2”, “c”=>“3”, “d”=>“4”}

Jesus.

On Mon, Jan 17, 2011 at 5:40 AM, RichardOnRails
[email protected] wrote:

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: (?rx)

See サービス終了のお知らせ

Kind regards

robert

On Thu, Jan 20, 2011 at 1:41 PM, RichardOnRails
[email protected] wrote:

(1…field_names.size).each { |name| h[name] = eval($ + ito_s) }
irb(main):001:0> rx = /(?‘name’\w+)\s*=\s*(?‘value’\S+)/

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.

Well, let’s see what we can do…

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

or

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

Or you use indexes directly.

:slight_smile:

Cheers

robert

On Jan 19, 5:10am, Robert K. [email protected] wrote:

=> /(?‘name’\w+)\s*=\s*(?‘value’\S+)/
Note, there is an alternative syntax: (?rx)

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

Kind regards

robert


remember.guy do |as, often| as.you_can - without
endhttp://blog.rubybestpractices.com/

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