Это должно делать работу в последних версиях 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]]]
Вот связанный вопрос с аналогичным решением. «Хитрость» заключается в методе Array#&
, который вычисляет пересечение (как заданную операцию) двух массивов. Это ассоциативная операция, поэтому мы можем применить ее к каждому подмассиву по очереди, сохраняя накопленный результат, поэтому inject
идеально подходит для него. Вкратце, array.inject(&:&)
приведет к наибольшему общему подмножеству элементов в каждом элементе array
. &:&
- это просто сокращение Ruby для создания Proc
из метода с именем &
и отправки его в виде блока в inject
вместо записи:
array.inject{|a,e| a & e}