2015-07-14 5 views
1

Каков самый короткий способ получить все комбинации K-элементов массива N-элементов, где K < = N? Мне удалось записать ниже:Самый короткий код для получения всех комбинаций K-элементов из массива N-элементов, где K <= N

> [1,2,3].instance_eval "(1..size).flat_map {|i| self.combination(i).to_a }" 

=> [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

Любые идеи, как избавиться от "instance_eval"? Это, кажется, не очень элангирует: \

+2

Как насчет назначения '[1,2,3]' имени? Как 'ary = [1,2,3]', а затем '(1..ary.size) .flat_map {| i | ary.combination (i) .to_a} ' Похоже на то, что вы вкратце –

+1

Почему вас волнует« кратчайший »? Длина кода не очень важна. –

+0

@NiklasB. nice, должен быть ответ – sschmeck

ответ

0

Одна версия, надеется, что это правильно.

x = [1, 2, 3] 
1.upto(x.size).reduce([]) { |a, i| a + x.permutation(i).map(&:sort).uniq.to_a } 
# => [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 
+0

Не самый эффективный способ генерации комбинаций: '[1,2,3,4] .permutation (3) .map (&: sort) .uniq == [1,2,3,4] .combination (3) .to_a # => true'. –

+0

@CarySwoveland, ты будешь. Я предпочитаю решение в комментариях niklas-b, но потом прочитал его. В этом тоже короткое решение. – sschmeck

2

Вот круто, короткий путь к реализации функции «булеан», если заказ/пустой список не имеет значения:

>>> [nil].product(*[1, 2, 3].map { |x| [nil, x] }).map(&:compact) 
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]] 
+0

спасибо ... ИМХО, ты сделал трюк и заставил меня узнать что-то новое – boggy

2

Я хотел бы сделать что-то вроде этого:

x = [1,2,3] 
1.upto(x.size).flat_map { |i| x.combination(i).to_a } 
#=> [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 
0
arr = [1,2,3,4] 

(2**arr.size).times.map do |i| 
    arr.each_with_index.with_object([]) { |(e,j),a| a << e if i[j] == 1 } 
end 
    #=> [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], 
    # [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]] 

Конечно, вы можете отсортировать массив, который будет возвращен, но вам понравится. Например:

(2**arr.size).times.map do |i| 
    arr.each_with_index.with_object([]) { |(e,j),a| a << e if i[j] == 1 } 
end.sort_by { |a| [a.size,a] } 
    #=> [[], 
    # [1], [2], [3], [4], 
    # [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], 
    # [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], 
    # [1, 2, 3, 4]]