From: Paul Smith Date: 2009-09-29T23:22:54+09:00 Subject: Re: Group by unique entries of a hash On Tue, Sep 29, 2009 at 2:38 PM, Robert Klemme wrote: > 2009/9/29 Paul Smith : >> On Tue, Sep 29, 2009 at 12:43 PM, Ne Scripter >> wrote: >>> I have two data sets loaded into a hash to give the following output >>> >>> "2efa4ba470",  "00000005" >>> "2efa4ba470",  "00000004" >>> "02adecfd5c",  "00000002" >>> "c0784b5de101",  "00000006" >>> "68c4bf10539",  "00000003" >>> "c0784b5de101",  "00000001" >>> >>> My code to get this is as follows: >>> >>>  source= "C:\\dummyFile.txt" >>>  hashMapping = Hash.new >>>  ocrIDMapping = Hash.new >>> >>>  IO.foreach(source.to_s) do |data| >>>    fields = data.split(",") >>>    hash = fields[0] >>>    ocrID = fields[1] >>>    hashMapping[ocrID] = hash >>>  end >>> >>>  hashMapping.sort{|a,b| a[1]<=>b[1]}.each { |elem| >>> >>>  puts "#{elem[1]}, #{elem[0]}"} >>> >>> I would like to alter my output to group my the first value to give an >>> output like this: >>> >>> "2efa4ba470",  "00000005", "00000004" >>> "02adecfd5c",  "00000002" >>> "c0784b5de101",  "00000006", "00000001" >>> "68c4bf10539",  "00000003" >>> >>> As you can see now only unique values are shown in the first field >>> however a list of the corresponding second field is formed, grouping the >>> results. Something like this I could do in SQL however I have never come >>> across it in Ruby so does anyone have any pointers? >> >> You want a hash where the key is the element you want to group on, and >> the 'item' is an array of all items with the shared key.  A bit like >> (untested): >> >> hashMapping = {} >> >> IO.foreach(source.to_s) do |data| >>   fields = data.split(",") >>   hash = fields[0] >>   ocrID = fields[1] >> >>   hashMapping[ocrID] ||= [] #If hashMapping has never seen this key >> before, make an empty array >> >>   hashMapping[ocrID] << hash #Add the new element to the array for this key >> >>  end > > It is slightly more efficient to do it in one step: > > (hashMapping[ocrID] ||= []) << hash > > Even nicer > > hashMapping = Hash.new {|h,k| h[k] = []} Is this defining a default element for the hash? I had a vague recollection you could do this but completely forgot how. I'd also rename the 'hash' variable to 'key' or something, I think it's less confusing. Then Your hashMapping can either be given the name 'hash', because that's what it is, or a name that's actually useful for describing what the mystical contents of the hash are. > ... > hashMapping[ocrID] << hash > > Kind regards > > robert > > -- > remember.guy do |as, often| as.you_can - without end > http://blog.rubybestpractices.com/ > > -- Paul Smith http://www.nomadicfun.co.uk paul@pollyandpaul.co.uk