2015-06-03 4 views
0

Я пытаюсь вызвать первый повторяющийся символ в моей строке в Ruby. Я определил входную строку, используя get.Поиск первого повторяющегося символа в строке Ruby

Как я могу назвать первый повторяющийся символ в строке?

Это мой код.

string = "#{gets}" 
print string 

Как я могу назвать символ из этой строки? не

Edit 1:

Это код, у меня сейчас, когда мой выход выходит ко мне Нет дублирует 26 раз. Я думаю, что мое утверждение if ошибочно написано.

string "abcade" 
puts string 
for i in ('a'..'z') 
if string =~ /(.)\1/ 
puts string.chars.group_by{|c| c}.find{|el| el[1].size >1}[0] 
else 
puts "no duplicates" 
end 
end 

Моя вторая не ставит выписки работает, но с для и если петли, она возвращает не дублирует 26 раз независимо от струна.

+1

ли Вы хотите знать, первый дубликат символа или индекс где это происходит? «Тестер» считается дублированным, поскольку у него есть два символа 'e', или вы собираетесь найти такие вещи, как' billing'? – tadman

+1

Вам нужно будет перебирать строку, сохраняя набор уже найденных символов и останавливать итерацию, как только набор содержит текущий символ. Один из способов доступа к строковым символам - использовать нотацию индекса массива, например, 's [0]' и т. Д. Другим является итерация с использованием 'each_char'. Есть много вариантов. –

+2

Добро пожаловать в переполнение стека. В вашем коде генерируется ошибка синтаксической ошибки "' undefined method 'string' для main: Object (NoMethodError) '. Возможно, это потому, что вы не скопировали свой код в вопрос правильно? «Вопросы, требующие помощи по отладке (« почему этот код не работает? ») Должны включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для его воспроизведения в самом вопросе. Вопросы без явного заявления о проблемах не полезны другим читателям. См.: [Как создать минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve). " –

ответ

4
s.chars.map { |c| [c, s.count(c)] }.drop_while{|i| i[1] <= 1}.first[0] 

С утонченной форме от Cary Swoveland:

s.each_char.find { |c| s.count(c) > 1 } 
+1

Рассмотрим упрощение: 's.each_char.find {| c | s.count (c)> 1} '. Обратите внимание, что 's.each_char' является перечислителем, который более эффективен, чем временный массив' s.chars'. В любом случае это решение второй интерпретации вопроса, который я дал в своем ответе. +1. –

4

Если я правильно понял вопрос правильно, то это возможный ответ:

the_string =~ /(.)\1/ 

Возвращает индекс первого дубликата письма.

Пример:

'1234556' =~ /(.)\1/ 
=> 4 

Edit:

Чтобы получить сам характер просто использовать $ 1:

$1 
=> "5" 

Edit 2:

В если statem ЛОР:

if my_string =~ /(.)\1/ 
    # do something with $1 
else 
    # there is no match 
end 
+0

Как это работает? Какая часть этого регулярного выражения идентифицирует дублирование? –

+0

Мне не нужен индекс строки, кроме самого символа. Так, например, для вашей строки я хотел бы, чтобы результат был равен 5. –

+1

@ShailiParikh Я специально спросил, что вы хотели в комментариях выше. Это действительно помогло бы сказать это впереди. – tadman

0

Я буду использовать положительный предпросмотр с String#[] методом:

"abcccddde"[/(.)(?=\1)/] #=> c 
+0

Увы, решение Дэвидрака достигнет того же результата, но проще. –

+0

@CarySwoveland Humm ... Я знаю, что мой сложный .. –

0

Как вариант:

str = "abcdeff" 
p str.chars.group_by{|c| c}.find{|el| el[1].size > 1}[0] 

печатает «F»

+0

Я также пытаюсь вывести значение, когда в строке нет дубликатов. Как я могу сделать это утверждение if? –

1

Я считаю, что вопрос может быть истолкован в любом из двух способов (ни с участием первого пары соседних символов, которые одинаковы) и предлагают решения для каждого из них.

Найти первый символ в строке, которая предшествует тот же характер

Я не считаю, что мы можем использовать регулярное выражение для этого (но хотелось бы быть опровергнуты). Я хотел бы использовать метод, предложенный в комментариях по @DaveNewton:

require 'set' 

def first_repeat_char(str) 
    str.each_char.with_object(Set.new) { |c,s| return c unless s.add?(c) } 
    nil 
end 

first_repeat_char("abcdebf") #=> b 
first_repeat_char("abcdcbe") #=> c 
first_repeat_char("abcdefg") #=> nil 

Найти первый символ в строке, которая появляется несколько раз

r =/
    (.) # match any character in capture group #1 
    .* # match any character zero of more times 
    ? # do the preceding lazily 
    \K # forget everything matched so far 
    \1 # match the contents of capture group 1 
    /x 

"abcdebf"[r] #=> b 
"abccdeb"[r] #=> b 
"abcdefg"[r] #=> nil 

Это регулярное выражение прекрасно, но дает предупреждение , "регулярное выражение имеет избыточный вложенный оператор повтора '*'". Вы можете игнорировать предупреждение или подавить его, делая что-то неуклюжим, как:

r = /([^#{0.chr}]).*?\K\1/ 

где ([^#{0.chr}]) означает «любой символ, кроме 0.chr в группе захвата 1».

Обратите внимание, что положительный lookbehind нельзя использовать здесь, так как они не могут содержать совпадения переменной длины (то есть, .*).

0

Возможно, вы можете сделать свой массив string и использовать detect. Это должно вернуть первый символ, где отсчет> 1.

string.split("").detect {|x| string.count(x) > 1} 
+0

Спасибо. Ты восхитителен! –

+0

Прохладный - не стесняйтесь отмечать это как правильное и upvote, если это работает :). Также, если вы ожидаете пробелы в '# {gets}', вы можете просто удалить их. – locoboy

2

Ниже метод может оказаться полезным, чтобы найти первое слово в строке

def firstRepeatedWord(string) 
    h_data = Hash.new(0) 
    string.split(" ").each{|x| h_data[x] +=1} 
    h_data.key(h_data.values.max) 
end 
+0

Ты потрясающий! –

Смежные вопросы