# Array and hash combine methods

**URL:** <https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305>\
**Category:** Ruby\
**Created:** [December 14, 2006, 2:24am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305 "2006-12-14T02:24:27Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [December 14, 2006, 2:24am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/1 "2006-12-14T02:24:27Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [December 14, 2006, 11:45am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/2 "2006-12-14T11:45:23Z")

</div>

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](http://facets.rubyforge.org/api/core/classes/Enumerable.html#M000555)

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [June 8, 2010, 5:52am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/3 "2010-06-08T05:52:12Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [June 8, 2010, 6:15am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/4 "2010-06-08T06:15:54Z")

</div>

On Jun 7, 9:52 pm, Juan M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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. 🙂

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [June 8, 2010, 6:33am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/5 "2010-06-08T06:33:22Z")

</div>

Gavin K. wrote:

> On Jun 7, 9:52ï¿½pm, Juan M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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. 🙂

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

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [June 8, 2010, 7:51am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/6 "2010-06-08T07:51:54Z")

</div>

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

* * *

From: Juan M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
To: ruby-talk ML [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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. 🙂

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

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [June 8, 2010, 2:28pm UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/7 "2010-06-08T14:28:24Z")

</div>

Robert K. wrote:

> 2010/6/8 Juan M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > > 
> > 
> > ï¿½[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.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [June 8, 2010, 9:36am UTC](https://www.ruby-forum.com/t/array-and-hash-combine-methods/79305/8 "2010-06-08T09:36:40Z")

</div>

2010/6/8 Juan M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > 
> 
> [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
