Most compact command for associate array 'totalling'?

  • Thread starter John Pritchard-williams
  • Start date
J

John Pritchard-williams

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

array[<string>]++


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
 
C

Chuck Remes

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

array[<string>]++


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....

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
 
S

Siep Korteling

Chuck said:
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
 
C

Chuck Remes

Chuck said:
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.

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
 
R

Robert Klemme

2008/8/8 Chuck Remes said:
Chuck said:
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
 
M

Marc Heiler

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.
 
J

John Pritchard-williams

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 :) 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
 
P

Peña, Botp

RnJvbTogSm9obiBQcml0Y2hhcmQtd2lsbGlhbXMgW21haWx0bzptb25vam9obm55QGdvb2dsZW1h
aWwuY29tXSANCiMgU28gY2FuIHNvbWVib2R5IGV4cGxhaW4gaW4gRW5nbGlzaCB3aGF0IGlzIGdv
aW5nIG9uIGhlcmUgPyANCiMgVGhpcyBpcyB2ZXJ5IHZlcnkgUnVieSB0byBtZSA6LSkgSSdtIGd1
ZXNzaW5nIHRoYXQgd2UgYXJlIA0KIyBoYW5naW5nIHRoYXQgYmxvY2sgb2YgdGhlICdzdG9yZScg
bWV0aG9kIG9mICdoJyBmcm9tIG5vdyBvbiA/IA0KIyBJIG1lYW46IHNvIHdoZW4gc29tZWJvZHkg
dGhlbiBjYWxscyBzb21ldGhpbmcgbGlrZToNCiMgDQojIGguc3RvcmUobXlrZXksbXl2YWx1ZSkg
aXQgd2lsbCBpbnZva2UgdGhlIGJsb2NrIHdoaWNoIHdpbGwgcmVzdWx0IGluOg0KIyBoW215a2V5
XT1teXZhbHVlIC0gYnV0IG9ubHkgaWYgJ215dmFsdWUnIGlzIG5pbCA/DQoNCm5vLiBuaWwgaXMg
YSB2YWx1ZSBhbmQgY291bGQgYmUgdmFsdWUgZm9yIGEgaGFzaCBrZXkuDQoNCnRyeQ0KICAgDQog
IGhbbXlrZXldID0gbmlsDQoNCg0KdGhlIGJsb2NrIGZvcm0gd2lsbCBpbnZva2UgdGhlIGJsb2Nr
IGlmIHRoZSBoYXNoIGtleSBkb2VzIG5vdCBleGlzdA0KDQp0cnkNCg0KICBoLmhhc19rZXk/IG15
a2V5DQoNCiANCiMgSXMgdGhpcyBhIHZlcnkgc3BlY2lmaWMgbWVjaGFuaXNtIHRvIGhhc2hlcyBv
ciBzb21ldGhpbmcgDQojIHJlYWxseSBnZW5lcmljPw0KDQppbWhvLCBpZiB5b3Ugd29yayBvbiBo
YXNoZXMsIHlvdSBzaG91bGQga25vdyBibG9jayBmb3JtIG9mIEhhc2gubmV3LiBTZWUgcnVieS1k
b2MgZm9yIGV4YW1wbGVzLg0KDQpraW5kIHJlZ2FyZHMgLWJvdHANCg==
 
J

John Pritchard-williams

# 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top