Ответ 1
a = [['1','2'],['a','b'],['x','y']]
a.first.product(*a[1..-1]).map(&:join)
У меня есть массив массивов, например:
[['1','2'],['a','b'],['x','y']]
Мне нужно объединить эти массивы в строку, содержащую все возможные комбинации всех трех наборов, только вперед. Я видел множество примеров всех возможных комбинаций множеств в любом порядке, это не то, что я хочу. Например, я не хочу, чтобы какой-либо из элементов в первом наборе приходил после второго набора, или любой из третьего набора, который должен был быть до первого или второго, и так далее. Итак, для вышеприведенного примера выход будет выглядеть следующим образом:
['1ax', '1ay', '1bx', '1by', '2ax', '2ay', '2bx', '2by']
Количество массивов и длина каждого набора являются динамическими.
Кто-нибудь знает, как это решить в Ruby?
a = [['1','2'],['a','b'],['x','y']]
a.first.product(*a[1..-1]).map(&:join)
Решено использовать рекурсивный, так называемый "Динамическое программирование" :
В коде:
def variations(a)
first = a.first
if a.length==1 then
first
else
rest = variations(a[1..-1])
first.map{ |x| rest.map{ |y| "#{x}#{y}" } }.flatten
end
end
p variations([['1','2'],['a','b'],['x','y']])
#=> ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"]
puts variations([%w[a b],%w[M N],['-'],%w[x y z],%w[0 1 2]]).join(' ')
#=> aM-x0 aM-x1 aM-x2 aM-y0 aM-y1 aM-y2 aM-z0 aM-z1 aM-z2 aN-x0 aN-x1 aN-x2
#=> aN-y0 aN-y1 aN-y2 aN-z0 aN-z1 aN-z2 bM-x0 bM-x1 bM-x2 bM-y0 bM-y1 bM-y2
#=> bM-z0 bM-z1 bM-z2 bN-x0 bN-x1 bN-x2 bN-y0 bN-y1 bN-y2 bN-z0 bN-z1 bN-z2
Вы также можете отменить логику, и с осторожностью вы сможете реализовать это нерекурсивно. Но рекурсивный ответ довольно прост.:)
Чисто, уменьшите с помощью продукта:
a = [['1','2'],['a','b'],['x','y']]
a.reduce() { |acc, n| acc.product(n).map(&:flatten) }.map(&:join)
# => ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"]