我有两个数组
a = [1,2,3,4]
b = [a,b,c,d,e,f]
我需要结合起来创建:
c = [[1,a],[1,b],[1,c],[1,d],[1,e],[1,f],[2,a],[2,b],...]
我会在product
Ruby 1.9 或更高版本中使用该方法,但我运行的是旧版本的 Ruby,并且此方法不存在。我不确定如何在c
不使用该product
方法的情况下创建。可以提供任何建议吗?
a.map {|ma| b.map { |mb| [ma, mb]} }
class Array
def product(other)
if block_given? then
each {|el| other.each {|other_el| yield [el, other_el]}}
else
res=[]
each{|el| other.each {|other_el| res << [el, other_el]}}
res
end
end
end
a = [1,2,3,4]
b = %w(a b c d e f)
p a.product(b) #[[1, "a"], [1, "b"], [1, "c"],...
a.product(b){|e| puts e.join}
#1a
#1b
#1c
#1d...
对于最近的 Ruby 版本,这段代码中会有一个return to_enum unless block_given?
地方,但 AFAIKto_enum
在旧的 Ruby 中不可用。实数product
需要多个参数;我还没有找到一种方法来做到这一点。
c = a.map{|x| b.map{|y| [x,y]}}.flatten(1)
根据您的 Ruby 版本的年龄,您可能需要使用:
c = a.map{|x| b.map{|y| [x,y]}}.inject([],:concat)
你正在做的是试图获得笛卡尔积。
我创建了一个名为的类CartesianArray
,它继承自Array
并为您提供了一个#product
方法。
class CartesianArray < Array
def initialize(array_one, array_two)
@array_one, @array_two = array_one, array_two
end
def product
results = []
@array_one.each do |a1|
@array_two.each do { |a2| results << [a1, a2] }
end
results
end
end
你可以像这样使用它:
# Test Code
numbers = [1,2,3,4]
letters = ['a','b','c','d','e','f']
cart_array = CartesianArray.new(numbers, letters)
p cart_array.product
[[1, "a"], [1, "b"], [1, "c"], [1, "d"], [1, "e"], [1, "f"], [2, "a"], [2, "b"], [2, "c"], [2, "d"], [2, "e"], [2, "f"], [3, "a"], [3, "b"], [3, "c"], [3, "d"], [3, "e"], [3, "f"], [4, "a"], [4, "b"], [4, "c"], [4, "d"], [4, "e"], [4, "f"]]
如果您不喜欢将其保留在该类中,那么我很确定您可以拉出该#product
方法并对其进行修改以适合您的代码。
获取Array#product
旧版 Rubies 的最简单方法是使用backports gem。它将这个方法添加到 Ruby 1.87和Ruby 1.9.2中。
当然,有比 -
(a+b).combination(2).map {|c| c if a.include?(c.join.to_i)}.compact
但我喜欢你可以用 Ruby 编写的不同可能的一种衬里。