[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Most compact command for associate array 'totalling'?

John Pritchard-williams

8/7/2008 9:59:00 PM

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
--
Posted via http://www.ruby-....

8 Answers

Chuck Remes

8/7/2008 10:13:00 PM

0


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

> 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


Siep Korteling

8/7/2008 10:27:00 PM

0

Chuck Remes 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
--
Posted via http://www.ruby-....

Chuck Remes

8/8/2008 1:36:00 AM

0


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

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

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


Robert Klemme

8/8/2008 7:45:00 AM

0

2008/8/8 Chuck Remes <cremes.devlist@mac.com>:
>
> On Aug 7, 2008, at 5:27 PM, Siep Korteling wrote:
>
>> Chuck Remes 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


--
use.inject do |as, often| as.you_can - without end

Marc Heiler

8/8/2008 9:31:00 AM

0

> 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.
--
Posted via http://www.ruby-....

John Pritchard-williams

8/8/2008 3:47:00 PM

0

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
--
Posted via http://www.ruby-....

Peña, Botp

8/9/2008 5:09:00 AM

0

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

John Pritchard-williams

8/9/2008 12:02:00 PM

0


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


--
Posted via http://www.ruby-....