Most compact command for associate array 'totalling'?

Ok - in ‘awk’ you can do this: (Where ‘array’ is empty initially)

array[]++

For instance:

array[“abc”]++; => a[“abc”]=1
array[“abc”]++; => a["abc’]=2

Which is really useful for tallying up a complete column of varying
values from a text file where you don’t know in advance the what may
appear in a column etc…

In Ruby, I have worked out a similar the equivalent to be: (with a Hash
now…)

a={};
a[“abc”]=a[“abc”].to_i+1;

But I"m sure there is a shorter way ? Better trick available here?

As an aside to ‘to_i’ is to turn the ‘nil’ into zero: is this safe to
assume this?

Thanks - sorry if this is stupid question…

John

On Aug 7, 2008, at 4:59 PM, John Pritchard-williams wrote:

a[“abc”]=a[“abc”].to_i+1;

But I"m sure there is a shorter way ? Better trick available here?

As an aside to ‘to_i’ is to turn the ‘nil’ into zero: is this safe to
assume this?

Thanks - sorry if this is stupid question…

No stupid questions; they’re all good.

Here’s a minor reworking of what you did to eliminate the #to_i.

a = Hash.new { |h,k| h[k] = 0 }
a[“abc”] += 1

The special form of Hash.new that I used above will automatically
initialize the bucket to 0 for any new key it receives, so you avoid
the problem with nil and #to_i.

cr

Chuck R. wrote:

On Aug 7, 2008, at 4:59 PM, John Pritchard-williams wrote:

a[“abc”]=a[“abc”].to_i+1;

But I"m sure there is a shorter way ? Better trick available here?

As an aside to ‘to_i’ is to turn the ‘nil’ into zero: is this safe to
assume this?

Thanks - sorry if this is stupid question…

No stupid questions; they’re all good.

Here’s a minor reworking of what you did to eliminate the #to_i.

a = Hash.new { |h,k| h[k] = 0 }
a[“abc”] += 1

The special form of Hash.new that I used above will automatically
initialize the bucket to 0 for any new key it receives, so you avoid
the problem with nil and #to_i.

cr

a = Hash.new(0)
a[“abc”] += 1

Has the same effect.

Regards,

Siep

On Aug 7, 2008, at 5:27 PM, Siep K. wrote:

to

The special form of Hash.new that I used above will automatically
initialize the bucket to 0 for any new key it receives, so you avoid
the problem with nil and #to_i.

cr

a = Hash.new(0)
a[“abc”] += 1

Has the same effect.

Quite true, but I find the block form to be a better “general case”
form to know since it is so much more flexible. But that’s just my
preference.

cr

2008/8/8 Chuck R. [email protected]:

On Aug 7, 2008, at 5:27 PM, Siep K. wrote:

Chuck R. wrote:

On Aug 7, 2008, at 4:59 PM, John Pritchard-williams wrote:

a = Hash.new { |h,k| h[k] = 0 }
a[“abc”] += 1

a = Hash.new(0)
a[“abc”] += 1

Has the same effect.

Quite true, but I find the block form to be a better “general case” form to
know since it is so much more flexible. But that’s just my preference.

That’s true in a way - although for this particular case I’d prefer
the solution with the default parameter. This can be slightly more
efficient at times because it does not insert a value on each query to
the Hash.

For other frequent cases, I use the block form. This is a typical
(for me) application:

items = Hash.new {|h,k| h[k] = []}

items[item.category] << item

Kind regards

robert

Quite true, but I find the block form to be a better “general case”
form to know since it is so much more flexible.

I guess you have a point here, but visually I find the shorter solution

a = Hash.new(0)
a[‘abc’] += 1

more appealing.

From: Marc H. [mailto:[email protected]]

I guess you have a point here, but visually I find the

shorter solution

a = Hash.new(0)

a[‘abc’] += 1

more appealing.

careful, it’s more than a face; the previous block example
creates/assigns objects when called.

compare this,

irb(main):001:0> h=Hash.new 0
=> {}
irb(main):002:0> h[1]
=> 0
irb(main):003:0> h[2]
=> 0
irb(main):004:0> h
=> {}

w this,

irb(main):005:0> h=Hash.new{|h,k| h[k]=0}
=> {}
irb(main):006:0> h[1]
=> 0
irb(main):007:0> h[2]
=> 0
irb(main):008:0> h
=> {1=>0, 2=>0}

and this,

irb(main):011:0* h=Hash.new{|h,k| 0}
=> {}
irb(main):012:0> h[1]
=> 0
irb(main):013:0> h[2]
=> 0
irb(main):014:0> h
=> {}

(note that Hash.new{|h,k| 0} may evolve to Hash.new{0} or Hash.new(0);
ie all of them do not assign/create to the hash)

the common denominator of the above is that they all do the ff (w same
result)

irb(main):021:0> h[1] += 1
=> 1
irb(main):022:0> h
=> {1=>1}

So if you ask me, i find the hash block form very generic.

kind regards -botp (just another block fan :slight_smile:

Thanks for the replies: in fact I also prefer this one:

//
a = Hash.new(0)
a[‘abc’] += 1
//

As it matches exactly the behaviour of the ‘awk’ program and its also
kinda neat looking.

On the other hand this solution is also really intriguing: ( and I note
the difference in behaviour as explained earlier in this post):

//
h=Hash.new{|h,k| h[k]=0}
//

So can somebody explain in English what is going on here ? This is very
very Ruby to me :slight_smile: I’m guessing that we are hanging that block of the
‘store’ method of ‘h’ from now on ? I mean: so when somebody then calls
something like:

h.store(mykey,myvalue) it will invoke the block which will result in:

h[mykey]=myvalue - but only if ‘myvalue’ is nil ?

Is this a very specific mechanism to hashes or something really generic?

Thanks again !

John

From: John Pritchard-williams [mailto:[email protected]]

So can somebody explain in English what is going on here ?

This is very very Ruby to me :slight_smile: I’m guessing that we are

hanging that block of the ‘store’ method of ‘h’ from now on ?

I mean: so when somebody then calls something like:

h.store(mykey,myvalue) it will invoke the block which will result in:

h[mykey]=myvalue - but only if ‘myvalue’ is nil ?

no. nil is a value and could be value for a hash key.

try

h[mykey] = nil

the block form will invoke the block if the hash key does not exist

try

h.has_key? mykey

Is this a very specific mechanism to hashes or something

really generic?

imho, if you work on hashes, you should know block form of Hash.new. See
ruby-doc for examples.

kind regards -botp

Is this a very specific mechanism to hashes or something

really generic?

imho, if you work on hashes, you should know block form of Hash.new. See
ruby-doc for examples.

Thanks ! Will check it out

Cheers

John