Как я могу найти первую повторяющуюся букву строки в Ruby?
У меня есть строка "teststring"
. Я хочу найти первый повторяющийся символ в Ruby.
У меня есть этот код Python:
def first_non_repeat_character(teststring)
unique=[]
repeated=[]
for character in teststring:
if character in unique:
unique.remove(character)
repeated.append(character)
else:
if not character in repeated:
unique.append(character)
if len(unique):
return unique[0]
else:
return false
Ответы
Ответ 1
Вы можете написать:
str = 'teststring'
arr = str.chars
(arr - (arr.difference(arr.uniq))).first
#= "e"
где Array#difference
определяется в моем ответе здесь.
Array#difference
похож на Array#-
. Разница проиллюстрирована в следующем примере:
a = [1,2,3,4,3,2,2,4]
b = [2,3,4,4,4]
a - b #=> [1]
a.difference b #=> [1, 3, 2, 2]
arr.difference(arr.uniq)
поэтому возвращает массив всех элементов e
of arr
, для которых arr.count(e) > 1
.
arr.difference(arr.uniq)
возвращает повторяющиеся символы, поэтому
arr - arr.difference(arr.uniq)
возвращает повторяющиеся символы, упорядоченные по порядку в arr
.
Ответ 2
def first_non_repeat_character(string)
string.chars.find { |character| string.count(character) == 1 }
end
first_non_repeat_character('teststring') # => "e"
Ответ 3
Это должно сделать трюк:
def first_non_repeat_character(teststring)
group = teststring.chars.group_by {|i| i}.find {|letter, group| group.one? }
group && group.first
end
Так как ruby 2.2.1 вы можете использовать group_by(&:itself)
Ответ 4
С кивком к @BroiSatse для основной идеи я предлагаю следующую вариацию в его ответе на цепочку в irb или pry console, если у вас есть Ruby 2.2+ с новым Object # сам:
'teststring'.chars.group_by(&:itself).values.select { |v| v.one? }.flatten.first
#=> "e"
Хорошая вещь об этом подходе (в отличие от определения метода) заключается в том, что легко отменить цепочку методов для отладки. Если вы не получите ответ, который вы ожидаете, просто продолжайте удалять хвост цепи методов, пока не найдете проблему.
Ответ 5
Другой:
'teststring'.each_char.with_object(Hash.new(0)) { |c, h| h[c] += 1 }.key(1)
#=> "e"
Шаг за шагом:
each_char
обходит каждого символа:
'teststring'.each_char.to_a
#=> ["t", "e", "s", "t", "s", "t", "r", "i", "n", "g"]
with_object
передает a Hash
со значением по умолчанию 0
в блок для подсчета каждого символа (возврат хэш):
'teststring'.each_char.with_object(Hash.new(0)) { |c, h| h[c] += 1 }
#=> {"t"=>3, "e"=>1, "s"=>2, "r"=>1, "i"=>1, "n"=>1, "g"=>1}
key
возвращает ключ (т.е. символ) для данного значения (т.е. с числом 1)
'teststring'.each_char.with_object(Hash.new(0)) { |c, h| h[c] += 1 }.key(1)
#=> "e"
Возможная оговорка: хотя реализация возвращает первый ключ для данного значения, в документации говорится:
Возвращает ключ вхождения данного значения.
Ответ 6
Вот пример, который учитывает прописные буквы. Например, если вы перейдете в
"sTresst" => "r"
def first_non_repeating_letter(s)
s.each_char do |char|
return char if s.downcase.count(char.downcase) < 2
end
""
end