30 votes

Combiner un tableau de tableaux en toutes les combinaisons possibles, en avant seulement, en Ruby

J'ai un tableau de tableaux, comme ça :

[['1','2'],['a','b'],['x','y']]

J'ai besoin de combiner ces tableaux en une chaîne contenant toutes les combinaisons possibles des trois ensembles, en avant seulement. J'ai vu beaucoup d'exemples de toutes les combinaisons possibles des ensembles dans n'importe quel ordre, ce n'est pas ce que je veux. Par exemple, je ne veux pas qu'un des éléments du premier ensemble vienne après le deuxième ensemble, ou qu'un élément du troisième ensemble vienne avant le premier, ou le deuxième, et ainsi de suite. Donc, pour l'exemple ci-dessus, la sortie serait :

['1ax', '1ay', '1bx', '1by', '2ax', '2ay', '2bx', '2by']

Le nombre de tableaux et la longueur de chaque ensemble sont dynamiques.

Quelqu'un sait-il comment résoudre ce problème en Ruby ?

62voto

Andrew Grimm Points 22996

Connaître votre Array#product :

a = [['1','2'],['a','b'],['x','y']]
a.first.product(*a[1..-1]).map(&:join)

8voto

Phrogz Points 112337

Résolu en utilisant une méthode récursive, dite "Programmation dynamique" approche :

  • Pour n tableaux, combinez les entrées du premier tableau avec chaque résultat des (n-1) tableaux restants.
  • Pour un tableau unique, la réponse est juste ce tableau.

En code :

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

Vous pouvez également inverser la logique et, en faisant attention, vous devriez être en mesure de l'implémenter de manière non récursive. Mais la réponse récursive est plutôt simple :)

5voto

Sply Splyeff Points 71

Pur, réduire avec le produit :

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"]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X