Как сочетать / перестановку в рубине? - PullRequest
5 голосов
/ 26 января 2012

У меня есть знакомый вопрос, который выглядит как перестановка / комбинация мира математики.

Как я могу добиться следующего с помощью рубина?

badges = "1-2-3"

badge_cascade = []
badges.split("-").each do |b|
  badge_cascade << b
end

Gives: => ["1", "2", "3"]

But I want it to be is:

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

Ответы [ 3 ]

7 голосов
/ 26 января 2012

Функциональный подход:

bs = "1-2-3".split("-")
strings = 1.upto(bs.size).flat_map do |n| 
  bs.permutation(n).map { |vs| vs.join("-") } 
end
#=> ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]
5 голосов
/ 26 января 2012

Вам необходимо использовать Array # перестановка метод для получения всех перестановок:

arr = "1-2-3".split '-' # => ["1", "2", "3"]
res = (1..arr.length).reduce([]) { |res, length|
  res += arr.permutation(length).to_a
}.map {|arr| arr.join('-')}

puts res.inspect
# => ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]

Позвольте мне объяснить код:

  1. Вы разбиваете строку на массив, передающий разделитель '-' в String # split метод

  2. Вам нужны все перестановки длины 1, 2, 3. Диапазон 1..arr.lengthпредставляет все эти длины.

  3. Вы собираете массив всех перестановок, используя Enumerable # reduce .Вы получите массив массивов здесь:

    [["1"], ["2"], ["3"], ["1", "2"], ["1", "3"], ["2", "1"], ["2", "3"], ["3", "1"], ["3", "2"], ["1", "2", "3"], ["1", "3", "2"], ["2", "1", "3"], ["2", "3", "1"], ["3", "1", "2"], ["3", "2", "1"]]
    
  4. Вы преобразуете все подмассивы этого массива в строки, используя Array # join с вашим '-' разделителем внутри Enumerable # map

2 голосов
/ 26 января 2012

Array#permutation(n) даст вам все перестановки длины n в виде массива массивов, так что вы можете называть это для каждой длины от 1 до количества цифр в значках .Последний шаг состоит в том, чтобы сопоставить их все обратно в строки, ограниченные -.

badges = "1-2-3"

badges_split = badges.split('-')

permutations = []

(1..badges_split.size).each do |n|
    permutations += badges_split.permutation(n).to_a
end

result = permutations.map { |permutation| permutation.join('-') }

Обновление: Я думаю, что использование Алексом reduceболее элегантный подход, но я пока оставлю здесь этот ответ на случай, если он будет полезен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...