Toni Schilling
Toni Schilling

Reputation: 117

Ruby: how to split a collection (Enumerable) in multiple (>2) partitions by some predicate?

Is there a function, to partition a collection (Enumerable) by some non-boolean predicate into more than 2 partitions? (my math knowledge got rusty - but I think, this was called "factorize" - or at least in German "Faktorisierung")
This follows my own yesterday question (Ruby: how to split a collection by predicate into two collections in ruby?)
and I wonder, is there another standard ruby method I just missed.

Here´s an example, showing the principle:

def factorize(eee)
  h={}; h.default_proc= proc{|h,k| h[k]=[] }
  eee.each{|e| k=yield e; h[k]<<e }
  h.values
end
factorize( 1..10 ){|n| n%3 }  #=> [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

Upvotes: 0

Views: 133

Answers (2)

Chris
Chris

Reputation: 36601

While the Enumerable#group_by solution is clearly the answer, it may be instructive to streamline your original attempt using #each_with_object.

def factorize(eee)
  eee.each_with_object({}) do |e, hsh|
    k = yield e
    hsh[k] ||= []
    hsh[k] << e
  end.values
end

factorize(1..10) { |x| x % 3 }
# => [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

Upvotes: 1

S&#233;bastien P.
S&#233;bastien P.

Reputation: 554

You can use group_by: https://apidock.com/ruby/v2_5_5/Enumerable/group_by

Example:

(1..10).group_by { |n| n % 3 }.values
=> [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

Upvotes: 3

Related Questions