Array#group_by

I posted this on the Rails list, but then I realised it would make more sense
over here:

···

-------

Just thought I'd share a function which has been really useful to me, for 2
reasons

1) It could easily help someone else
2) People might be able to make it work better or point out where it's not
optimal

class Array
  # Groups elements of an array based on a user-defined condition
  #
  # Each element from this array is passed to the block, and the returned value
  # determines the key under which it will be stored in the output hash
  #
  # If no block is given then the array indices will be used as the hash keys
  def group_by
    hsh = {}
    self.dup.each_with_index do |element, i|
      if block_given?
        key = yield element
      else
        key = i
      end
      hsh[key] ||= []
      hsh[key] << element
    end
    hsh
  end
end

} I posted this on the Rails list, but then I realised it would make more sense
} over here:
}
} -------
}
} Just thought I'd share a function which has been really useful to me, for 2
} reasons
}
} 1) It could easily help someone else
} 2) People might be able to make it work better or point out where it's not
} optimal

See
http://redcorundum.blogspot.com/2006/06/enumerablebucketby-and-uniqby-and.html
for a post of mine from June that covers that, and more.

--Greg

···

On Wed, Nov 29, 2006 at 10:55:37PM +0900, Gareth Adams wrote:

Gareth Adams a écrit :

I posted this on the Rails list, but then I realised it would make more sense
over here:

-------

Just thought I'd share a function which has been really useful to me, for 2 reasons

1) It could easily help someone else
2) People might be able to make it work better or point out where it's not optimal

class Array
  # Groups elements of an array based on a user-defined condition
  # # Each element from this array is passed to the block, and the returned value
  # determines the key under which it will be stored in the output hash
  #
  # If no block is given then the array indices will be used as the hash keys
  def group_by
    hsh = {}
    self.dup.each_with_index do |element, i|
      if block_given?
        key = yield element
      else
        key = i
      end
      hsh[key] ||=
      hsh[key] << element
    end
    hsh
  end
end

Hi,

thanks for the tip. I have q question with do you use a ".dup" on the line self.dup.each_with_index do |element, i| ? Facets has a similar function (partition_by), but don't use a ".dup" before iterating:

http://facets.rubyforge.org/api/core/classes/Enumerable.html#M000526

···

--
Bruno Michel

Here's an improved version:

  module Enumerable
    def group_by
      hsh = Hash.new{|hsh, key| hsh[key] = }
      if block_given?
        each{|obj| hsh[yield(obj)].push(obj) }
      else
        each_with_index{|obj, i| hsh[i].push(obj) }
      end
      hsh
    end
  end

Cheers,
Daniel Schierbeck

···

On Wed, 2006-11-29 at 22:55 +0900, Gareth Adams wrote:

class Array
  # Groups elements of an array based on a user-defined condition
  #
  # Each element from this array is passed to the block, and the returned value
  # determines the key under which it will be stored in the output hash
  #
  # If no block is given then the array indices will be used as the hash keys
  def group_by
    hsh = {}
    self.dup.each_with_index do |element, i|
      if block_given?
        key = yield element
      else
        key = i
      end
      hsh[key] ||=
      hsh[key] << element
    end
    hsh
  end
end

i'm unlear how this adds to inject:

   harp:~ > cat a.rb
   words = %w( foo bar foobar )

   grouped = words.inject Hash.new{|h,k| h[k] = } do |h,k|
     h[k[0,1]] << k; h
   end

   p grouped

   harp:~ > ruby a.rb
   {"b"=>["bar"], "f"=>["foo", "foobar"]}

which you can one-line if you wish:

   harp:~ > cat a.rb
   words = %w( foo bar foobar )
   p words.inject({}){|h,k| (h[k[0,1]] ||= ) << k; h}

   harp:~ > ruby a.rb
   {"b"=>["bar"], "f"=>["foo", "foobar"]}

regards.

-a

···

On Thu, 30 Nov 2006, Bruno Michel wrote:

Gareth Adams a écrit :

I posted this on the Rails list, but then I realised it would make more sense
over here:

-------

Just thought I'd share a function which has been really useful to me, for 2 reasons

1) It could easily help someone else
2) People might be able to make it work better or point out where it's not optimal

class Array
  # Groups elements of an array based on a user-defined condition
  # # Each element from this array is passed to the block, and the returned value
  # determines the key under which it will be stored in the output hash
  #
  # If no block is given then the array indices will be used as the hash keys
  def group_by
    hsh = {}
    self.dup.each_with_index do |element, i|
      if block_given?
        key = yield element
      else
        key = i
      end
      hsh[key] ||=
      hsh[key] << element
    end
    hsh
  end
end

Hi,

thanks for the tip. I have q question with do you use a ".dup" on the line self.dup.each_with_index do |element, i| ? Facets has a similar function (partition_by), but don't use a ".dup" before iterating:

http://facets.rubyforge.org/api/core/classes/Enumerable.html#M000526

--
if you want others to be happy, practice compassion.
if you want to be happy, practice compassion. -- the dalai lama

If you don't care about duplicates, just use Set#classify.

···

--
Lou.

Louis J Scoras wrote:

If you don't care about duplicates, just use Set#classify.

Why isn't there an Array#classify, which would return a hash of arrays, preserving duplicates?

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Beats me =) I'm not arguing against such a method; just pointing out
that there's already something that might get the job done. A lot of
times people use arrays to represent sets without realizing it.

···

On 11/29/06, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Why isn't there an Array#classify, which would return a hash of arrays,
preserving duplicates?

--
Lou.

Louis J Scoras wrote:

···

On 11/29/06, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Why isn't there an Array#classify, which would return a hash of arrays,
preserving duplicates?

Beats me =) I'm not arguing against such a method; just pointing out
that there's already something that might get the job done. A lot of
times people use arrays to represent sets without realizing it.

I wasn't arguing either. I had forgotten about the useful Set#classify, and thought why not have one for Array too? I can't see any theoretical reason not to.

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407