Как я могу напечатать строку и сделать паузу, когда есть полная остановка или «…» в Ruby?

#ruby #iteration #pause

#ruby #итерация #пауза

Вопрос:

Я пытаюсь создать программу на Ruby, которая выводит текст и делает паузу для каждой полной остановки «.» или «…» в строке. Я получил это до сих пор, но не знаю, что делать дальше.

 def talk(text, speed = 0.008)
    pause = speed * 100
    text.each_char do |char| 
        print char
        if char == '.'
            sleep(pause)
        end
        sleep(speed) 
    end
    return
end

# e.g. talk("I can see something... It's getting closer... Oh no.")
 

Он отлично останавливается на одну полную остановку, но, очевидно, не работает для трех подряд, поскольку он просто повторяет паузу три раза. Я скорее новичок и изо всех сил пытаюсь найти решение. Спасибо за чтение

Ответ №1:

Вот мое предложение — выводите все . буквы s по мере их появления, переходя в режим ожидания перед печатью следующего символа.

 def talk(text, speed = 0.008)
    pause = speed * 100
    last_char = nil # keep track of the previous character.

    text.each_char do |char|
        if char == '.' 
            # no sleep at all for periods
            print('.')
        else
            # we're going to print something, if the last character was a period,
            # pause before doing it.  
            sleep(pause) if last_char == '.'
            print char
            # finally, a regular sleep 
            sleep(speed)
        end
        # and update the last character we saw
        last_char = char
    end
end
 

Конечно, есть много разных способов решить эту проблему!

Ответ №2:

 def talk(text, speed = 0.008)
  pause = speed * 100
  r = /(.{3}|.)/
  text.split(r).each do |str|
    if str.match?(r)
      sleep(pause)
    else
      print str
    end
  end
  puts
end
 
 talk("Mary had .a lit...tle .lamb", 0.04)
  #=> Mary had a little lamb
              ^     ^      ^
 

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

Шаги следующие.

 text = "Mary had .a lit...tle .lamb"
speed = 0.04
pause = speed * 100
r = /(.{3}|.)/
 

Это регулярное выражение гласит: «сопоставьте три периода или ( | ) один период в группе захвата 1″ (группа захвата определяется круглыми скобками)». Это не то же самое, что /(.|.{3})/ , который соответствовал бы каждому периоду каждой группы из трех по отдельности (то есть, . before | будет успешным для каждого периода, части группы или нет).

 a = text.split((r))
  #=> ["Mary had ", ".", "a lit", "...", "tle ", ".", "lamb"]
 

Смотрите Строку #split , которая объясняет необходимость для группы захвата включать строки разделения в возвращаемый массив.

Продолжение,

 a.each do |str|
  if str.match?(r)
    sleep(pause)
  else
    print str
  end
end
 

Это печатает (без символа новой строки) "Mary had " , спит в течение четырех секунд, печатает "a lit" , спит еще четыре секунды и так далее.

 puts
 

Этот последний оператор необходим для печати символа новой строки для завершения строки.


Другой способ — внести несколько небольших изменений в метод, указанный в вопросе.

 def talk(text, speed = 0.008)
  pause = speed * 100
  text.squeeze('.').each_char do |char| 
    if char == '.'
      sleep(pause)
    else
      print char
    end
  end
  puts
end
 

Смотрите String#squeeze, который преобразует каждую строку из двух или более периодов в один период.

Этот метод отличается от предыдущего тем, что он обрабатывает два или более трех периодов подряд.