I have an array of N arrays A_i: [A_1,A_2,…,A_N].
I want to iterate over the cartesian product A_1xA_2…xA_N.
Is there a simple way of doing this without specifying N?
I have an array of N arrays A_i: [A_1,A_2,…,A_N].
I want to iterate over the cartesian product A_1xA_2…xA_N.
Is there a simple way of doing this without specifying N?
This thread seems to be a pretty thorough treatment of the idea:
http://www.ruby-forum.com/topic/95519 . It was the first result of a
google
search on “ruby cross_product”.
Handy G. wrote:
I have an array of N arrays A_i: [A_1,A_2,…,A_N].
I want to iterate over the cartesian product A_1xA_2…xA_N.
Is there a simple way of doing this without specifying N?
ary = [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
ary.first.product(*ary.drop(1))
# => [
# => [1, 3, 6], [1, 3, 7], [1, 3, 8], [1, 3, 9],
# => [1, 4, 6], [1, 4, 7], [1, 4, 8], [1, 4, 9],
# => [1, 5, 6], [1, 5, 7], [1, 5, 8], [1, 5, 9],
# => [2, 3, 6], [2, 3, 7], [2, 3, 8], [2, 3, 9],
# => [2, 4, 6], [2, 4, 7], [2, 4, 8], [2, 4, 9],
# => [2, 5, 6], [2, 5, 7], [2, 5, 8], [2, 5, 9]
# => ]
jwm
On Tue, 14 Sep 20 10 17:13:11 +0200, Jörg W Mittag wrote:
# => [1, 3, 6], [1, 3, 7], [1, 3, 8], [1, 3, 9], # => [1, 4, 6], [1, 4, 7], [1, 4, 8], [1, 4, 9], # => [1, 5, 6], [1, 5, 7], [1, 5, 8], [1, 5, 9], # => [2, 3, 6], [2, 3, 7], [2, 3, 8], [2, 3, 9], # => [2, 4, 6], [2, 4, 7], [2, 4, 8], [2, 4, 9], # => [2, 5, 6], [2, 5, 7], [2, 5, 8], [2, 5, 9] # => ]
jwm
That looks so cool I wish I knew what it does.
ary.first is the first element of ary.
ary.product(one, two, …) is the cartesian product of ary with its
arguments.
ary.drop(1) is ary[1…-1], all the elements of ary but the first.
ary.product(*ary.drop(1)) passes each element of ary[1…-1] to
product() as an argument, making it equivalent to
ary.product(ary[1], ary[2], …, ary[-1])
Whoops, that should be ary.first.product, of course.
2010/9/14 Jörg W Mittag [email protected]:
=> [1, 3, 6], [1, 3, 7], [1, 3, 8], [1, 3, 9],
=> [1, 4, 6], [1, 4, 7], [1, 4, 8], [1, 4, 9],
=> [1, 5, 6], [1, 5, 7], [1, 5, 8], [1, 5, 9],
=> [2, 3, 6], [2, 3, 7], [2, 3, 8], [2, 3, 9],
=> [2, 4, 6], [2, 4, 7], [2, 4, 8], [2, 4, 9],
=> [2, 5, 6], [2, 5, 7], [2, 5, 8], [2, 5, 9]
=> ]
This looks nice. How did you do the formatting?
If destruction is allowed, we can do:
irb(main):013:0> ary = [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
=> [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
irb(main):014:0> pp ary.shift.product(*ary)
[[1, 3, 6],
[1, 3, 7],
[1, 3, 8],
[1, 3, 9],
[1, 4, 6],
[1, 4, 7],
[1, 4, 8],
[1, 4, 9],
[1, 5, 6],
[1, 5, 7],
[1, 5, 8],
[1, 5, 9],
[2, 3, 6],
[2, 3, 7],
[2, 3, 8],
[2, 3, 9],
[2, 4, 6],
[2, 4, 7],
[2, 4, 8],
[2, 4, 9],
[2, 5, 6],
[2, 5, 7],
[2, 5, 8],
[2, 5, 9]]
=> nil
Kind regards
robert
Robert K. wrote:
  # =>  [1, 3, 6], [1, 3, 7], [1, 3, 8], [1, 3, 9],
  # =>  [1, 4, 6], [1, 4, 7], [1, 4, 8], [1, 4, 9],
  # =>  [1, 5, 6], [1, 5, 7], [1, 5, 8], [1, 5, 9],
  # =>  [2, 3, 6], [2, 3, 7], [2, 3, 8], [2, 3, 9],
  # =>  [2, 4, 6], [2, 4, 7], [2, 4, 8], [2, 4, 9],
  # =>  [2, 5, 6], [2, 5, 7], [2, 5, 8], [2, 5, 9]
  # => ]
This looks nice. How did you do the formatting?
By hand
Though I assume Hirb or awesome_print could probably do it
automatically.
If destruction is allowed, we can do:
irb(main):013:0> ary = [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
=> [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
irb(main):014:0> pp ary.shift.product(*ary)
[[1, 3, 6],
…
=> nil
That’s nice. Having toyed with Scala and Haskell, mutation just feels
so dirty to me. I guess I need some re-education to get back into
the idiomatic Ruby mindset.
jwm
2010/9/15 Jörg W Mittag [email protected]:
=> [
=> [1, 3, 6], [1, 3, 7], [1, 3, 8], [1, 3, 9],
=> [1, 4, 6], [1, 4, 7], [1, 4, 8], [1, 4, 9],
=> [1, 5, 6], [1, 5, 7], [1, 5, 8], [1, 5, 9],
=> [2, 3, 6], [2, 3, 7], [2, 3, 8], [2, 3, 9],
=> [2, 4, 6], [2, 4, 7], [2, 4, 8], [2, 4, 9],
=> [2, 5, 6], [2, 5, 7], [2, 5, 8], [2, 5, 9]
=> ]
This looks nice. How did you do the formatting?
By hand
14:09:29 ~$ gem19 install ‘By hand’
ERROR: could not find gem By hand locally or in a repository
14:09:58 ~$
Hm…
=> nil
That’s nice. Having toyed with Scala and Haskell, mutation just feels
so dirty to me. I guess I need some re-education to get back into
the idiomatic Ruby mindset.
Unfortunately there is no #slice which has two return values. If
there was we could do
a,b = arr.slice 0,1
But we can do this to achieve the same (i.e. non destructively
partitioning):
irb(main):016:0> a=(1…5).to_a
=> [1, 2, 3, 4, 5]
irb(main):017:0> y=(x=a.dup).slice! 0,1
=> [1]
irb(main):018:0> x
=> [2, 3, 4, 5]
irb(main):019:0> a
=> [1, 2, 3, 4, 5]
Well, I guess the simplest approach is still
irb(main):001:0> a=(1…5).to_a
=> [1, 2, 3, 4, 5]
irb(main):002:0> x,*y = a
=> [1, 2, 3, 4, 5]
irb(main):003:0> x
=> 1
irb(main):004:0> y
=> [2, 3, 4, 5]
So we can do
irb(main):026:0> ary = [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
=> [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
irb(main):027:0> x, *y = ary
=> [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
irb(main):028:0> pp x.product(*y)
[[1, 3, 6],
[1, 3, 7],
[1, 3, 8],
[1, 3, 9],
[1, 4, 6],
[1, 4, 7],
[1, 4, 8],
[1, 4, 9],
[1, 5, 6],
[1, 5, 7],
[1, 5, 8],
[1, 5, 9],
[2, 3, 6],
[2, 3, 7],
[2, 3, 8],
[2, 3, 9],
[2, 4, 6],
[2, 4, 7],
[2, 4, 8],
[2, 4, 9],
[2, 5, 6],
[2, 5, 7],
[2, 5, 8],
[2, 5, 9]]
=> nil
Kind regards
robert
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs