我想将Ruby数组(可能包含一些子数组)扩展到另一个数组数组中,就像在这些示例中一样:
示例1:[:foo, :bar]
[
[:foo, :bar]
]
示例2:[:foo, :bar, [:ki, :ku]]
[
[:foo, :bar, :ki],
[:foo, :bar, :ku]
]
示例3:[:foo, :bar, :baz, [:a, :i, :u, :e, :o], :qux]
[
[:foo, :bar, :baz, :a, :qux],
[:foo, :bar, :baz, :i, :qux],
[:foo, :bar, :baz, :u, :qux],
[:foo, :bar, :baz, :e, :qux],
[:foo, :bar, :baz, :o, :qux]
]
示例4:[:foo, :bar, :baz, [:a, :i, :u, :e, :o], [1, 2], :qux]
[
[:foo, :bar, :baz, :a, 1, :qux],
[:foo, :bar, :baz, :i, 1, :qux],
[:foo, :bar, :baz, :u, 1, :qux],
[:foo, :bar, :baz, :e, 1, :qux],
[:foo, :bar, :baz, :o, 1, :qux],
[:foo, :bar, :baz, :a, 2, :qux],
[:foo, :bar, :baz, :i, 2, :qux],
[:foo, :bar, :baz, :u, 2, :qux],
[:foo, :bar, :baz, :e, 2, :qux],
[:foo, :bar, :baz, :o, 2, :qux]
]
示例5:[:foo, [[], :c], :bar]
[
[:foo, [], :bar],
[:foo, :c, :bar]
]
示例6:[:foo, [[:a, :b], :c], :bar]
[
[:foo, [:a, :b], :bar],
[:foo, :c, :bar]
]
注意:只应展开子数组。这就是为什么,在例子5& 6,子子阵列未扩展。
非常感谢任何建议或代码。
答案 0 :(得分:8)
我使用product
的想法来实现此功能:
def trans(a)
b = a.map{|e| [e].flatten(1)}
b.first.product(*b.slice(1..-1))
end
例如,此代码:
puts trans([:foo, :bar]).inspect
puts trans([:foo, :bar, :baz, [:a, :i, :u, :e, :o], [1, 2], :qux]).inspect
puts trans([:foo, [[], :c], :bar]).inspect
puts trans([:foo, [[:a, :b], :c], :bar]).inspect
给出这个:
[[:foo, :bar]]
[[:foo, :bar, :baz, :a, 1, :qux],
[:foo, :bar, :baz, :a, 2, :qux],
[:foo, :bar, :baz, :i, 1, :qux],
[:foo, :bar, :baz, :i, 2, :qux],
[:foo, :bar, :baz, :u, 1, :qux],
[:foo, :bar, :baz, :u, 2, :qux],
[:foo, :bar, :baz, :e, 1, :qux],
[:foo, :bar, :baz, :e, 2, :qux],
[:foo, :bar, :baz, :o, 1, :qux],
[:foo, :bar, :baz, :o, 2, :qux]]
[[:foo, [], :bar],
[:foo, :c, :bar]]
[[:foo, [:a, :b], :bar],
[:foo, :c, :bar]]
编辑:上述代码的说明。
一般的想法是我们想要数组中所有元素的产品。如果您查看Array#product的文档,您会发现它符合您的要求 - 我们只需要适当地调用它。
首先,product
对数组进行操作,因此我们必须确保原始数组中的所有项都是数组。这是函数第一行的任务:
b = a.map{|e| [e].flatten(1)}
我们正在使用map
转换数组中的所有元素。转换生成一个内部带有元素e
的数组,然后展平这个新数组。原始元素是一个数组,或者它不是;如果它不是一个数组,[e].flatten(1)
将什么也不做,将返回[e]
;如果它是一个数组,[e]
将评估为[[x]]
,然后将其展平为[x]
。 1
告诉flatten
只有1级深度。
然后我们要做的就是在第一个元素上调用product
作为参数传递修改后的数组的其余元素:
b.first.product(*b.slice(1..-1))
在这里,b.slice(1..-1)
表示:从第2个一直到最后一个从b获取元素。最后,星号表示我们不想将数组作为参数传递,而是传递数组的元素。
答案 1 :(得分:2)
似乎你希望有一个有问题的阵列元素的笛卡尔积。 此代码应该适合您:
array = [:foo, :bar, :baz, [:a, :i, :u, :e, :o], [1, 2], :qux]
array.inject([[]]) do |product,element|
result = []
if element.is_a?(Array)
product.each do |tuple|
element.each do |last|
result << tuple + [last]
end
end
else
product.each do |tuple|
result << tuple + [element]
end
end
result
end
您可以通过将条件移动到循环来简化它,但这会降低效率。
答案 2 :(得分:1)
考虑到您使用的是示例而不是明确的内容,我建议您通过 Array method's documentation 进行拖网。首先,请看下面的方法:
.combination.to_a
.shift
.transpose
.flatten
.zip
.take
你如何实现取决于你是否知道在每种情况下你正在改变什么,或者你是否正在尝试构建通用的东西(即扩展Array类。对于每一个我都将输入数组操作到目标数组中。示例1很简单:
input = [:foo,:bar]
target = Array.new
target << input => [[:foo,:bar]]
对于其他示例,有多种方法可以实现,具体取决于您尝试执行的操作,以及您希望ruby在使用输入时如何知道该怎么做。在示例2中,第一个是直接写:
input = [:foo, :bar, [:ki, :ku]]
target = Array.new
target << [input[0], input[1], input[2][0]]
target << [input[0], input[1], input[2][1]]
或使用数组方法:
target = input.pop
target = [input, input].zip(target).flatten
target = [target[0..(target.size/2)-1], target[target.size/2..-1]]
或者如果您不知道包含子数组的数组部分,您可以检测到它:
input.each do |i|
if i.class == Array
holding = i
end
end
这实际上取决于你想要如何识别和操纵数组!