Project

General

Profile

Feature #4151

Enumerable#categorize

Added by akr (Akira Tanaka) over 9 years ago. Updated over 2 years ago.

Status:
Rejected
Priority:
Normal
Target version:
[ruby-core:33683]

Description

=begin
Hi.

How about a method for converting enumerable to 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]}

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:

  • :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]
--
Tanaka Akira

Attachment: enum-categorize.patch
=end


Files

associate.pdf (145 KB) associate.pdf marcandre (Marc-Andre Lafortune), 07/01/2012 04:48 AM
feature4151.pdf (78.7 KB) feature4151.pdf Eregon (Benoit Daloze), 07/01/2012 04:57 AM

Related issues

Related to Ruby master - Feature #6669: A method like Hash#map but returns hashFeedbackmatz (Yukihiro Matsumoto)Actions
Related to Ruby master - Feature #666: Enumerable::to_hashRejectedmatz (Yukihiro Matsumoto)10/20/2008Actions
Related to Ruby master - Feature #5662: inject-accumulate, or Haskell's mapAccum*Rejected11/23/2011Actions
Related to Ruby master - Feature #5008: Equal rights for Hash (like Array, String, Integer, Float)Rejectedmatz (Yukihiro Matsumoto)07/10/2011Actions
Related to Ruby master - Feature #7241: Enumerable#to_h proposalRejected10/30/2012Actions
Related to Ruby master - Feature #7292: Enumerable#to_hClosedmarcandre (Marc-Andre Lafortune)11/07/2012Actions
Related to Ruby master - Feature #7793: New methods on HashAssignedmatz (Yukihiro Matsumoto)Actions

Also available in: Atom PDF