From: Robert Klemme Date: 2010-09-15T21:16:01+09:00 Subject: Re: Iterate over a cartesian product. 2010/9/15 Jörg W Mittag : > Robert Klemme wrote: >> 2010/9/14 Jörg W Mittag : >>> Handy Gandy 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] >>>    # => ] >> 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... > 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. 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 -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/