From: Robert Klemme Date: 2008-03-25T21:49:08+09:00 Subject: Re: numbers of a record in an array 2008/3/25, Jesús Gabriel y Galán : > On Tue, Mar 25, 2008 at 11:23 AM, Robert Klemme > wrote: > > 2008/3/25, Jesús Gabriel y Galán : > > > On Tue, Mar 25, 2008 at 10:09 AM, Bu Mihai wrote: > > > > a have an array array=["a","b","c","a","b"] > > > > how can i find the numbers of "a", "b","c" items in the array? > > > > irb(main):006:0> a = %w{a b a c b a c c} > > > => ["a", "b", "a", "c", "b", "a", "c", "c"] > > > irb(main):007:0> h = Hash.new {|h,k| h[k] = 0} > > > => {} > > > irb(main):008:0> a.each {|x| h[x] += 1} > > > => ["a", "b", "a", "c", "b", "a", "c", "c"] > > > irb(main):009:0> h > > > => {"a"=>3, "b"=>2, "c"=>3} > > > > Here's another > > > > irb(main):001:0> a = %w{a b a c b a c c} > > > > => ["a", "b", "a", "c", "b", "a", "c", "c"] > > irb(main):002:0> a.inject(Hash.new(0)){|cnt,e| cnt[e]+=1; cnt} > > > > => {"a"=>3, "b"=>2, "c"=>3} > > > > Jesús, note that you do not need the block form of Hash.new because of > > the way + works. It is sufficient to make 0 the default element. > > > Oh, that's right. I'm so used to that form for defaulting to an array :-). > You say the reason is because of how + works, but is it not the reason > the fact that 0 is an immediate value > of which there's only one instance? So having the same reference to > the 0 object works, whereas having the same > reference to an array (for example) wouldn't achieve the desired effect? No, this has nothing to do with immediate values. The reason why this works is that an operation is used that creates a new instance (Fixnum#+ in this case) and uses assignment to place a new value on every iteration. This also works with arrays and other non immediate and even mutable instances: irb(main):001:0> collector = Hash.new [] => {} irb(main):002:0> 10.times {|i| collector[i%3] += [i]} => 10 irb(main):003:0> collector => {0=>[0, 3, 6, 9], 1=>[1, 4, 7], 2=>[2, 5, 8]} You can even freeze the default object irb(main):007:0> collector = Hash.new([].freeze) => {} irb(main):008:0> 10.times {|i| collector[i%3] += [i]} => 10 irb(main):009:0> collector => {0=>[0, 3, 6, 9], 1=>[1, 4, 7], 2=>[2, 5, 8]} Kind regards robert -- use.inject do |as, often| as.you_can - without end