Cela devrait faire le travail au cours des dernières versions Ruby:
a.length.downto(1).map{|i| a.combination(i).map{|sub| sub.inject(&:&)}}
#=> [[[]], [[], [3, 4], [2], [1]], [[3, 4], [2], [2, 3, 4], [1], [1, 3, 4], [1, 2]], [[2, 3, 4], [1, 3, 4], [1, 2], [1, 2, 3, 4]]]
Here's une question connexe avec une solution similaire. Le "truc" est dans la méthode Array#&
, qui calcule l'intersection (comme une opération ensemble) des deux tableaux. C'est associative opération, donc nous pouvons l'appliquer sur chaque sous-tableau à tour de rôle, en gardant le résultat accumulé, par conséquent inject
est parfait pour cela. En bref, array.inject(&:&)
se traduira par un plus grand sous-ensemble commun d'éléments dans chaque membre de array
. &:&
est juste un raccourci Ruby pour faire une Proc
de méthode nommée &
et de le soumettre comme un bloc à inject
, au lieu d'écrire:
array.inject{|a,e| a & e}
@Mladen, Jablonović, c'est une solution élégante impressionante. Pouvez-vous mettre à jour votre réponse pour en expliquer un peu plus comment cela fonctionne? Plus précisément, qu'est-ce que '&: &' et comment cela fonctionne-t-il avec 'Enumerable # inject'? –