Как разбить строку, используя регулярные выражения для каждого числа - PullRequest
0 голосов
/ 12 февраля 2019

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

Если форматирование выглядит следующим образом:

2 + 3 * ( 2 + 2 )

Я беру это значение, разбиваю его на каждый пробел в массив, превращаю каждое число в число с плавающей точкой, и моя программа может рекурсивно решить эту проблему в соответствии с PEMDAS.Однако, если пользователь должен был прийти и ударить это в:

2+3*(2+2)

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

22+33*(22+22)

Это ломается.

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

Мой желаемый результат:

["2.0", "+", "3.0", "*", "(", "2.0", "+", "2.0", ")"]

Iесть следующий, который не работает

better_format = ss.scan(/\d*\.\d*|\+|\-|\*|\%\/|\(\)/) => ["2.0", "+", "3.0", "*", "", "2.0", "+", "2.0", "", ""]

Мне нужно немного информации.Насколько я понимаю, мое выражение ищет:

  • Любое количество цифр, за которым следует один период, за которым следует любое количество цифр
  • Любой из следующих символов '+, -, *, /,%, (,) '

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Целые числа

Вместо того, чтобы отфильтровывать то, что вы хотите, используя #scan, вы также можете отфильтровать то, что вы не хотите, используя #split.

'2 + 3 * ( 2 + 2 )'.split(/\s+|\b|(?=\W)/)
#=> ["2", "+", "3", "*", "(", "2", "+", "2", ")"]

'22+33*(22+22)'.split(/\s+|\b|(?=\W)/)
#=> ["22", "+", "33", "*", "(", "22", "+", "22", ")"]

Это регулярное выражение разбивается на:

  • Пробел (\s+), когда, например, указан 22 +.
  • Граница слова (\b)когда, например, 22+ дано.
  • Символ, за которым следует символ, не состоящий из слов ((?=\W)), когда, например, дано *(.

Floats

Вышеприведенное работает для целых чисел, но не для чисел с плавающей точкой.Для правильного разбора поплавков нам нужно написать \b самостоятельно.\b равно (?<=\w)(?!\w)|(?<!\w)(?=\w), что делает интенсивным использование lookarounds .Если мы применим это только к десятичным и точкам, это приведет к (?<=[\d.])(?![\d.])|(?<![\d.])(?=[\d.]).

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

float_boundary = /(?<=[\d.])(?![\d.])|(?<![\d.])(?=[\d.])/
non_float_boundary = /(?<![\d.])(?![\d.])/
regex = /\s+|#{float_boundary}|#{non_float_boundary}/

'22.22+33*(22.34+22.1)'.split(/\s+|\b|(?=\W)/)
#=> ["22", ".", "22", "+", "33", "*", "(", "22", ".", "34", "+", "22", ".", "1", ")"]

'22.22+33*(22.34+22.1)'.split(regex)
#=> ["22.22", "+", "33", "*", "(", "22.34", "+", "22.1", ")"]
0 голосов
/ 13 февраля 2019
R = /
    (?:       # begin a non-capture group
      (?<=    # begin a positive lookbehind
        \d    # match a digit
        [ ]?  # optionally match a space
      )       # end positive lookbehind
      -       # match a minus sign
    )         # end non-capture group
    |         # or
    -?        # optionally match a minus sign
    \d+       # match one or more digits           
    (?:       # begin a non-capture group
      \.      # match a period 
      \d+     # match one or more digits
    )         # end non-capture group
    ?         # optionally match non-capture group above
    |         # or
    \S        # match a non-whitespace character
    /x        # free-spacing regex definition mode

def doit(str)
  str.scan(R)
end

doit "2 + 3 * ( 2 + 2 )"
  #=> ["2", "+", "3", "*", "(", "2", "+", "2", ")"] 
doit "2+3*(2+2)"
  #=> ["2", "+", "3", "*", "(", "2", "+", "2", ")"] 
doit "22+33*(22+22)"
  #=> ["22", "+", "33", "*", "(", "22", "+", "22", ")"] 
doit "(22+33)!*(22-12)"
  #=> ["(", "22", "+", "33", ")", "!", "*", "(", "22",
  #    "-", "12", ")"] 
doit "(22-33)*(22/-12)"
  #=> ["(", "22", "-", "33", ")", "*", "(", "22", "/",
  #    "-12", ")"] 
doit "(22+33.4)*(22/-12.3)"
  #=> ["(", "22", "+", "33.4", ")", "*", "(", "22", "/",
  #    "-12.3", ")"] 
doit "2-1"
  #=> ["2", "-", "1"] 
doit ".2"
  #=> [".", "2"] 

Регулярное выражение обычно записывается следующим образом.

/(?:(?<=\d )-)|-?\d+(?:\.\d+)?|\S/

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

0 голосов
/ 12 февраля 2019

Вы можете использовать

s.scan(/\d*\.?\d+|[-+\/*%()]/)

См. Демонстрационную версию regex .

Или, чтобы соответствовать любому типу без пробелов, кроме чисел:

s.scan(/\d*\.?\d+|[^\d\s]/)
                  ^^^^^^^

См. Демонстрационную версию Ruby .

Подробности

  • \d*\.?\d+ - 0 или более цифр, необязательно . а затем 1+ цифр
  • | - или
  • [-+\/*%()] - -, +, /, *, %, ( или )
  • [^\d\s] - любой символ, кроме пробела и цифры
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...