Array and hash combine methods

Just thought I’d post a solution I came up with to finding
combinations (as in, permutations and combinations) of arrays. For
example, combining:

[1,2] and [3,4,5]

should return:

[[1,3],[1,4],[1,5],[2,3],[2,4],[2,5]]

which is easy enough. But I wanted something that combine several
arrays at once, ie:

[[1,2],[3,4,5],[6,7]].combine
=> [[1, 3, 6], [1, 3, 7], [1, 4, 6], [1, 4, 7], [1, 5, 6], [1, 5, 7],
[2, 3, 6], [2, 3, 7], [2, 4, 6], [2, 4, 7], [2, 5, 6], [2, 5, 7]]

I had a look around and couldn’t find anything that worked for more
than two arrays, so I wrote my own:

class Array
#expects self to be an array of arrays, returns all the combinations
possible
def combine
#checks
output_length = 1
periods = []
reverse.each { |sub_arr|
periods << output_length
raise “combine needs an array of arrays!” if !sub_arr.is_a? Array
raise “combine is meaningless unless all the sub_arrays have at
least one element!” if sub_arr.length == 0
output_length *= sub_arr.length
}
periods.reverse!
output = (1…output_length).map { Array.new(length) }
output.each_index { |i|
periods.each_index { |j|
output[i][j] = self[j][(i/periods[j])%self[j].length]
}
}
output
end
end

And the corresponding hash method:

class Hash
#expects a hash eg. {a=>[1,2], b=>[3,4]}
#returns an array eg. [{a=>1,b=>3}, {a=>1,b=4}, {a=>2,b=>3},
{a=>2,b=4}]
def combine
values.combine.map { |comb|
Hash[*keys.zip(comb).inject([]) { |arr,e| arr + e }]
}
end
end

I’d love to hear other solutions to this problem - and where I should
have looked to find them… Oh and if anyone has suggestions for a
better name than ‘combine’, that’d be great.

Cheers,
-glen.

Le jeudi 14 décembre 2006 02:22, glen a écrit :

which is easy enough. But I wanted something that combine several
arrays at once, ie:

[[1,2],[3,4,5],[6,7]].combine
=> [[1, 3, 6], [1, 3, 7], [1, 4, 6], [1, 4, 7], [1, 5, 6], [1, 5, 7],
[2, 3, 6], [2, 3, 7], [2, 4, 6], [2, 4, 7], [2, 5, 6], [2, 5, 7]]

There is a Enumerable.combinations method in ruby facets which works
like
this. Take a look at :

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

glen wrote:

Just thought I’d post a solution I came up with to finding
combinations (as in, permutations and combinations) of arrays. For
example, combining:

[1,2] and [3,4,5]

should return:

[[1,3],[1,4],[1,5],[2,3],[2,4],[2,5]]

which is easy enough. But I wanted something that combine several
arrays at once, ie:

[[1,2],[3,4,5],[6,7]].combine
=> [[1, 3, 6], [1, 3, 7], [1, 4, 6], [1, 4, 7], [1, 5, 6], [1, 5, 7],
[2, 3, 6], [2, 3, 7], [2, 4, 6], [2, 4, 7], [2, 5, 6], [2, 5, 7]]

And why not something like:

[1,2].combine([3,4]).combine([5,6,7])

I do that with this code:

class Array
def combine(otherArray)
aux = []
self.each do |self_elem|
otherArray.each do |other_elem|
aux << [self_elem,other_elem]
end
end
aux.map {|elem| elem.flatten }
end
end

Juan M.

On Jun 7, 9:52 pm, Juan M. [email protected] wrote:

glen wrote:

Just thought I’d post a solution I came up with to finding
combinations (as in, permutations and combinations) of arrays. For
example, combining:

Juan, it would appear that glen posted this question/tip 3.5 years
ago. Any reason you were responding to it now? (Which, in turn, lured
me into responding. :slight_smile:

Gavin K. wrote:

On Jun 7, 9:52�pm, Juan M. [email protected] wrote:

glen wrote:

Just thought I’d post a solution I came up with to finding
combinations (as in, permutations and combinations) of arrays. For
example, combining:

Juan, it would appear that glen posted this question/tip 3.5 years
ago. Any reason you were responding to it now? (Which, in turn, lured
me into responding. :slight_smile:

Sure Gavin, I’m looking for something like that and found this post.
Maybe result useful to someone. You have another solution for this?
Thanks

The examples seem to be missing
If there is code snippets, it would help.
-Kamal.


From: Juan M. [email protected]
To: ruby-talk ML [email protected]
Sent: Tue, June 8, 2010 12:33:24 AM
Subject: Re: array and hash combine methods

Gavin K. wrote:

On Jun 7, 9:52�pm, Juan M. [email protected] wrote:

glen wrote:

Just thought I’d post a solution I came up with to finding
combinations (as in, permutations and combinations) of arrays. For
example, combining:

Juan, it would appear that glen posted this question/tip 3.5 years
ago. Any reason you were responding to it now? (Which, in turn, lured
me into responding. :slight_smile:

Sure Gavin, I’m looking for something like that and found this post.
Maybe result useful to someone. You have another solution for this?
Thanks

Robert K. wrote:

2010/6/8 Juan M. [email protected]:

�[1,2].combine([3,4]).combine([5,6,7])
� �end
� �aux.map {|elem| elem.flatten }
�end
end

I’d rather do this:

module Enumerable
def combine(enum)
if block_given?
each do |*a|
enum.each do |*b|
yield *a, *b
end
end
self
else
enum_for(:combine, enum)
end
end
end

[1,2].combine([3,4]) do |*a|
p a
end

puts “--------------”

[1,2].combine([3,4]).each do |*a|
p a
end

puts “--------------”

[1,2].combine([3,4]).combine([5,6]) do |*a|
p a
end

puts “--------------”

[1,2].combine([3,4]).combine([5,6]).each do |*a|
p a
end

Kind regards

robert

Great, I’ll probe it,also I add a fix to my code:

class Array
def combine(otherArray)
aux = []
return otherArray if self.empty? #this line
self.each do |self_elem|
otherArray.each do |other_elem|
aux << [self_elem,other_elem]
end
end
aux.map {|elem| elem.flatten }
end
end

Juan M.

2010/6/8 Juan M. [email protected]:

[1,2].combine([3,4]).combine([5,6,7])
end
aux.map {|elem| elem.flatten }
end
end

I’d rather do this:

module Enumerable
def combine(enum)
if block_given?
each do |*a|
enum.each do |*b|
yield *a, *b
end
end
self
else
enum_for(:combine, enum)
end
end
end

[1,2].combine([3,4]) do |*a|
p a
end

puts “--------------”

[1,2].combine([3,4]).each do |*a|
p a
end

puts “--------------”

[1,2].combine([3,4]).combine([5,6]) do |*a|
p a
end

puts “--------------”

[1,2].combine([3,4]).combine([5,6]).each do |*a|
p a
end

Kind regards

robert