[RCR] Enumerable#group_by

Hi,

I propose the addition of Enumerable#group_by which is a generalization
of Enumerable#partition.

module Enumerable
def group_by(store=Hash.new)
self.each do |elem|
group = yield elem
(store[group] ||= []) << elem
end
store
end
end

For example:

%w(This is a list of words).group_by {|word| word.size}

would result in:

{5=>[“words”], 1=>[“a”], 2=>[“is”, “of”], 4=>[“This”, “list”]}

Is this useful enough to include into Ruby?

Regards,

Michael

Michael Neumann wrote:

Hi,

Moin!

%w(This is a list of words).group_by {|word| word.size}

would result in:

{5=>[“words”], 1=>[“a”], 2=>[“is”, “of”], 4=>[“This”, “list”]}

Is this useful enough to include into Ruby?

I have used this before when I needed to find files which have the same
content. Basically I did this: (Yes, I used exactly the same name and
almost the same logic as you. :))

module Enumerable
def group_by
result = Hash.new { |h, k| h[k] = Array.new }
self.each do |item|
group = yield(item)
result[group] << item
end
return result
end
end

And later:

files.group_by { |file| hash_file(file) }

So, yes, I think that this would make a great extension to the standard
Ruby.

Regards,
Michael

More regards,
Florian Gross

Hi,

At Wed, 26 May 2004 02:16:27 +0900,
Michael Neumann wrote in [ruby-talk:101382]:

I propose the addition of Enumerable#group_by which is a generalization
of Enumerable#partition.

I think it has been proposed also as Enumerable#classify. Here
is a patch I made at that time.

Index: enum.c

···

===================================================================
RCS file: /cvs/ruby/src/ruby/enum.c,v
retrieving revision 1.45
diff -U2 -p -d -r1.45 enum.c
— enum.c 14 Apr 2004 04:06:24 -0000 1.45
+++ enum.c 21 Apr 2004 08:37:31 -0000
@@ -362,4 +362,37 @@ enum_partition(obj)
}

+static VALUE
+classify_i(i, hash)

  • VALUE i, hash;
    +{
  • VALUE k = rb_yield(i);
  • VALUE ary = rb_hash_aref(hash, k);
  • if (NIL_P(ary)) {
  • rb_hash_aset(hash, k, ary = rb_ary_new());
  • }
  • rb_ary_push(ary, i);
  • return Qnil;
    +}

+/*

    • call-seq:
    • enum.classify {| x | block }  => hash
      
    • Returns a hash containing the items in enum classified.
  • */

+static VALUE
+enum_classify(obj)

  • VALUE obj;
    +{
  • VALUE hash = rb_hash_new();
  • rb_iterate(rb_each, obj, classify_i, hash);
  • return hash;
    +}

/*

  • call-seq:
    @@ -930,4 +963,5 @@ Init_Enumerable()
    rb_define_method(rb_mEnumerable,“inject”, enum_inject, -1);
    rb_define_method(rb_mEnumerable,“partition”, enum_partition, 0);
  • rb_define_method(rb_mEnumerable,“classify”, enum_classify, 0);
    rb_define_method(rb_mEnumerable,“all?”, enum_all, 0);
    rb_define_method(rb_mEnumerable,“any?”, enum_any, 0);


Nobu Nakada

I say it is. But if you just want something you can download and use
anywhere without reimplementing, ‘extensions’ implements
Enumerable#partition_by. Different name, same thing.

Cheers,
Gavin

···

On Wednesday, May 26, 2004, 3:16:27 AM, Michael wrote:

For example:

%w(This is a list of words).group_by {|word| word.size}

would result in:

{5=>[“words”], 1=>[“a”], 2=>[“is”, “of”], 4=>[“This”, “list”]}

Is this useful enough to include into Ruby?