From: "marcandre (Marc-Andre Lafortune)" Date: 2012-12-04T02:24:29+09:00 Subject: [ruby-core:50532] [ruby-trunk - Feature #7444] Array#product_set Issue #7444 has been updated by marcandre (Marc-Andre Lafortune). stomar (Marcus Stollsteimer) wrote: > > Not really. `arrays.product_set.to_a` and `arrays.inject(:product)` give only the same result if `arrays.size == 2`. If < or > 2, results are different. > > Please elaborate. I'm not sure how I was not clear, but in concrete examples: [].inject(:product) # => nil [].product_set.to_a # => [[]] [[1,2]].inject(:product) # => [1,2] [[1,2]].product_set.to_a # => [[1], [2]] [[1,2], [3,4], [5,6]].inject(:product) # => [[[1, 3], 5], [[1, 3], 6], [[1, 4], 5], [[1, 4], 6], [[2, 3], 5], [[2, 3], 6], [[2, 4], 5], [[2, 4], 6]] [[1,2], [3,4], [5,6]].product_set.to_a # => [[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]] # etc... As noted, I also have to call `to_a` on `product_set` to compare. ---------------------------------------- Feature #7444: Array#product_set https://bugs.ruby-lang.org/issues/7444#change-34376 Author: marcandre (Marc-Andre Lafortune) Status: Open Priority: Normal Assignee: matz (Yukihiro Matsumoto) Category: core Target version: next minor I'd like to propose `Array#product_set` to return the product set of arrays (aka cartesian product) deck = [1..13, %i(spades hearts diamond clubs)].product_set # => <#Enumerator ...> deck.first(2) # => [[1, :spades], [2, :spades]] `product_set` would return an enumerator if no block is given. It should raise an error if an element of the array is not an Enumerable, like Array#transpose or #zip do. Although `Array.product` would be acceptable too, I feel that an instance method of array is best in the case, in the same way that `transpose` is an instance method and not a class method. The name "product_set" is a correct mathematical term. Although the synonym "cartesian_product" would also be acceptable, I propose "product_set" because it is shorter and cute too. I feel it is even clearer than `product`; the first time I head of `product` I was convinced that `[2,3,7].product # => 42`. Addressing objections raised in #6499: 1) This is not for the sake of symmetry, but because often we have an array of the arrays we want a product of. It is cumbersome to write `arrays.first.product(*arrays[1..-1])` or similar and it hides what is going on. Writing `arrays.product_set` is much nicer. 2) The goal is not mainly to get a lazy version, but more to make the API better. The fact that it returns an Enumerator if no block is given is just a bonus :-) 3) [].product_set.to_a # => [[]] This can be seen from a cardinality argument, or for example because `array.repeated_permutation(n) == Array.new(n, array).product_set.to_a` and `array.repeated_permutation(0) == [[]]`. -- http://bugs.ruby-lang.org/