On 2010/12/12 20:13, Tanaka Akira wrote: > Hi. > > How about a method for converting enumerable to hash? There are already such methods. At least group_by. Your proposal seems to be a very special way to convert an enumerable to a hash. > enum.categorize([opts]) {|elt| [key1, ..., val] } -> hash > > categorizes the elements in _enum_ and returns a hash. > > The block is called for each elements in _enum_. > The block should return an array which contains > one or more keys and one value. > > p (0..10).categorize {|e| [e % 3, e % 5] } > #=> {0=>[0, 3, 1, 4], 1=>[1, 4, 2, 0], 2=>[2, 0, 3]} I'm trying to understand your example. Let me make a table. original value return_value[0] return_value[1] 0 0 0 1 1 1 2 2 2 3 0 3 4 1 4 5 2 0 6 0 1 7 1 2 8 2 3 9 0 4 10 1 0 I think I get the idea of how this is supposed to work. But I'm not sure what the actual use cases would be. Can you give some? For this variant, a Ruby equivalent is: h = {} (0..10).each do |e| h[e%3] ||= [] h[e%3] << e%5 end p h Or shorter: h = {} (0..10).each { |e| (h[e%3] ||= []) << e%5 } p h I admit that it is more elegant if the initialization and the final line can be avoided, but I think that's an issue that can be dealt with separately. > The keys and value are used to construct the result hash. > If two or more keys are provided > (i.e. the length of the array is longer than 2), > the result hash will be nested. > > p (0..10).categorize {|e| [e&4, e&2, e&1, e] } > #=> {0=>{0=>{0=>[0, 8], > # 1=>[1, 9]}, > # 2=>{0=>[2, 10], > # 1=>[3]}}, > # 4=>{0=>{0=>[4], > # 1=>[5]}, > # 2=>{0=>[6], > # 1=>[7]}}} > > The value of innermost hash is an array which contains values for > corresponding keys. > This behavior can be customized by :seed, :op and :update option. > > This method can take an option hash. > Available options are follows: Who will be able to remember exactly what these options are,...? Most other methods, in particular on Enumerables, don't have that many options. I think that's for a good reason. Regards, Martin. > - :seed specifies seed value. > - :op specifies a procedure from seed and value to next seed. > - :update specifies a procedure from seed and block value to next seed. > > :seed, :op and :update customizes how to generate > the innermost hash value. > :seed and :op behavies like Enumerable#inject. > > If _seed_ and _op_ is specified, the result value is generated as follows. > op.call(..., op.call(op.call(seed, v0), v1), ...) > > :update works as :op except the second argument is the block value itself > instead of the last value of the block value. > > If :seed option is not given, the first value is used as the seed. > > # The arguments for :op option procedure are the seed and the value. > # (i.e. the last element of the array returned from the block.) > r = [0].categorize(:seed => :s, > :op => lambda {|x,y| > p [x,y] #=> [:s, :v] > 1 > }) {|e| > p e #=> 0 > [:k, :v] > } > p r #=> {:k=>1} > > # The arguments for :update option procedure are the seed and the array > # returned from the block. > r = [0].categorize(:seed => :s, > :update => lambda {|x,y| > p [x,y] #=> [:s, [:k, :v]] > 1 > }) {|e| > p e #=> 0 > [:k, :v] > } > p r #=> {:k=>1} > > The default behavior, array construction, can be implemented as follows. > :seed => nil > :op => lambda {|s, v| !s ? [v] : (s<< v) } > > Note that matz doesn't find satisfact in the method name, "categorize". > [ruby-dev:42681] > > Also note that matz wants another method than this method, > which the hash value is the last value, not an array of all values. > This can be implemented by enum.categorize(:op=>lambda {|x,y| y}) { ... }. > But good method name is not found yet. > [ruby-dev:42643] -- #-# Martin J. Dst, Professor, Aoyama Gakuin University #-# http://www.sw.it.aoyama.ac.jp mailto:duerst / it.aoyama.ac.jp