lib/cartesian.rb in Cartesian-0.2.1 vs lib/cartesian.rb in Cartesian-0.2.3
- old
+ new
@@ -41,24 +41,32 @@
#
# or, if mixed in into Array,
#
# [1,2].cartesian %w(A B) #=> [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
#
- def Cartesian.product(first, second)
+ # optional parameter {:flatten => true}
+ #
+ def Cartesian.product(first, second, params={})
+ params[:flatten] ||= true
+
result = []
first.each do |a|
second.each do |b|
- result << [a, b]
+ if params[:flatten] == true
+ result << [a, b].flatten
+ else
+ result << [a, b]
+ end
end
end
result
end
# Cartesian.product for mixin.
#
- def cartesian(other)
- Cartesian.product(self, other)
+ def cartesian(other, params={})
+ Cartesian.product(self, other, params)
end
# Behaves as product, except for the elements are joined.
#
# Cartesian::joined_cartesian( [1,2], %w(A B) ) #=> ["1A", "1B", "2A", "2B"]
@@ -104,9 +112,41 @@
# +to_a+, i.e., be convertible to array.
#
def x(other)
CartesianIterator.new(self, other)
end
+
+ # Concise way of iterating multi-dimensionally
+ # over the same array or range.
+ #
+ # For instance,
+ #
+ # for x,y,z in [0,1]**3
+ # puts [x, y, z].join(',')
+ # end
+ #
+ # produces the following output
+ #
+ # 0,0,0
+ # 0,0,1
+ # 0,1,0
+ # 0,1,1
+ # 1,0,0
+ # 1,0,1
+ # 1,1,0
+ # 1,1,1
+ #
+ # It also works with Range objects.
+ #
+ def **(fixnum)
+ return self if fixnum <= 1
+ iter = CartesianIterator.new(self, self)
+ (fixnum-2).times do
+ iter.x(self)
+ end
+ iter
+ end
+ alias :power! :**
end
class Array
include Cartesian
end