Robert Klemme
1/15/2007 3:47:00 PM
On 15.01.2007 14:36, Stefano Zacchiroli wrote:
> Answering to myself ...
>
> On Mon, Jan 15, 2007 at 10:29:11PM +0900, Stefano Zacchiroli wrote:
>> def delete(o)
>> super(o)
>> @arity[o] -= 1
>> @arity.delete o if @arity[o] == 0
>> end
>
> The above is of course wrong, elements get remove before their arity
> reach 0.
>
>> => nil # aargh, do I need to alias again in
>> # derived classes? that's too bad ...
>
> Apparently so, alias makes a *copy* of the method :(
>
> Here is a better version:
>
> require 'set'
> class MultiSet < Set
> def initialize
> super
> @arity = {}
> end
> attr_reader :arity
> def add(o)
> super(o)
> @arity[o] = 0 unless @arity.member? o
> @arity[o] += 1
> end
> def delete(o)
> @arity[o] -= 1
> if @arity[o] == 0
> super(o)
> @arity.delete o
> end
> end
> alias << add
> end
>
You can as well use a Hash as multi set:
irb(main):001:0> multi_set = Hash.new 0
=> {}
irb(main):002:0> multi_set['foo'] += 1
=> 1
irb(main):003:0> multi_set
=> {"foo"=>1}
irb(main):004:0> multi_set['foo'] += 1
=> 2
irb(main):005:0> multi_set
=> {"foo"=>2}
irb(main):006:0> multi_set['bar'] += 1
=> 1
irb(main):007:0> multi_set['bar']
=> 1
irb(main):008:0> multi_set['foo']
=> 2
irb(main):009:0> multi_set
=> {"foo"=>2, "bar"=>1}
irb(main):010:0> multi_set['foo'] -= 1
=> 1
irb(main):011:0> multi_set
=> {"foo"=>1, "bar"=>1}
irb(main):012:0> multi_set['xxx']
=> 0
Of course this does not prevent values other than numbers as well as
negative numbers.
Ah, and btw, I'm not sure whether it's a good idea to have a MultiSet
class inherit Set: after all Set /is (the special case of) a/ MultiSet -
not the other way round.
Kind regards
robert