Как проверить, содержит ли две строки один и тот же символ в рубине

Я хочу сделать слово unscarambler в рубине. скажем, если у меня есть слова в массиве

 words = ["foo","ofo"]

как я могу сравнить это с другой строкой типа "oof" и возвращать истинное значение

Ответ 1

Это можно сделать следующим образом.

words = ["foo", "ofo", "goo"]
target = "foo"
target_size = target.size
  #=> 3 
target_sorted = target.each_char.sort
  #=> ["f", "o", "o"] 

words.select { |w| anagram?(target_size, target_sorted, w) }
  #=> ["foo", "ofo"] 

Типичный способ anagram? записывается в следующем виде:

def anagram?(target_size, target_sorted, w)
  return false unless w.size == target_size
  w.each_char.sort == target_sorted
end

Однако я подумал, что может быть быстрее:

  • Шаг через символы target
  • Найдите индекс i совпадающего символа в w
  • Если совпадение найдено, удалите w[i]
  • Если совпадение не найдено (i #=> nil), верните false
  • return true, если false не возвращается ранее

Это можно реализовать таким образом:

def anagram?(target_size, target, w)
  return false unless target.size == w.size
  wcpy = w.dup
  target.each_char do |c|
    i = wcpy.index(c)
    return false unless i
    wcpy[i] = ''
  end
  true
end

words.select { |w| anagram?(target_size, target, w) }
  #=> ["foo", "ofo"]

Мне нужно будет сравнить эти два дня.

[Изменить: Мы также можем написать:

def anagram?(w1, w2)
  return false unless w1.size == w2.size
  w1.chars.difference(w2.chars).empty?
end

Помощник Array#difference определяется здесь.

Ответ 2

Если все строки в массиве являются перестановками друг друга, то:

words = ["foo", "ofo"]
str = "foo"

words[0].split("").sort == str.split("").sort