From: MonkeeSage Date: 2007-12-06T09:10:01+09:00 Subject: Re: hash On Dec 5, 4:49 pm, Johnathan Smith wrote: > hey guys > > sorry for the whole mix up! I appreciate all the help I've received > especially as im new to ruby! im also new to the forum and should have > tried to stick it our with the first threat! so i hope i havn't offended > any of you by this. Nah! Any mistake you might make, we've already done that and worse (probably several times). :) > that aside, i really hope you can help me resolve this problem. > > Jordan, the code you gave me worked successfully. However, it just deals > with the the two types i gave you, author and type.Its partially my > fault for not explaining properly becuase i hope it could deal with any > information after the tag. is this possible to achieve? Sure it is. The code I gave you can be expanded, but it was mainly just for you to get started with, because it is fragile (as you saw from my mis-post). Even with the correct "author[8..-1]", if you accidentally leave out the space between the "Author: Name" line, it will still clip the first letter off the name ([number..number] means to grab a smaller section from a larger container, and -1 has the special meaning of the last item; so author[8..-1] means to get the characters from number 8 to the end). What you really want is something more flexible, that will allow for those kinds of mistakes and still do the right thing in almost every case. That is a regular expression. It lets you give it a pattern which has certain rules, and matches a string in different ways based on those rules. And this is just what Phrogz' code is doing: # we'll get rid of linecount since you can # get that information directly from your hash # and we'll store the hashes as subhashes # underneath a main one, keyed by "Tag:" value database = {} File.open('reference.txt') { | handle | last_tag = nil # we'll use this to keep track of # the last tag we've seen, see below handle.each { | line | # the following regexp says to match: # ^ = starting at the first char # (\w+) = 1 or more "word" characters (a-z / 0-9) # : = followed by a literal colon # \s* = then zero or more "space" characters # ([\w+,\s]+) = 1 or more "word/space/," characters # $ = with nothing else until the end of line # # any string meeting that criteria is a match and m is # the match data, however if the string doesn't match # e.g., a blank line, m is nil m = line.match(/^(\w+):\s*([\w+,\s]+)$/) if m # if m is a match (i.e., not nil) if m[1] == 'Tag' # we want to add a key to the hash # since this is a "Tag:" line # when we used the () in the regexp # that told ruby we only care about # those chars, and we can access # them in the match object with m[n] # i.e, m[1] means whatever part of the # line matched (\w+) last_tag = m[2].chomp database[last_tag] = {} # make a subhash as the value # now we have, e.g., # database["ref1"] = {} else # it's not a "Tag:" line, so we add it as key, value # to the subhash we created for the last tag key we # created in the hash database[last_tag][m[1].downcase] = m[2].chomp # e.g., database["ref1"]["type"] = "Journal" end end } } # now print it print "# of Tags: ", database.length, "\n\n" print "Contents: ", database.inspect, "\n\n" puts database["ref2"]["author"] ======== This outputs: # of Tags: 3 Contents: {"ref1"=>{"author"=>"Little, S R", "type"=>"Book"}, "ref2"=>{"author"=>"Smith, J", "type"=>"Journal"}, "ref3"=>{"author"=>"Williams, M", "type"=>"Conference Paper"}} Smith, J > again sorry for the mix up > cheers > > -- > Posted viahttp://www.ruby-forum.com/. No worries :) HTH, Jordan