Объяснить Ruby Commify метод большого целого - PullRequest
0 голосов
/ 13 сентября 2010

Я нашел этот фрагмент в сети, и цель состоит в том, чтобы ввести любое число, включая числа с десятичными знаками ... 99999999 => 99 999 999. Я вижу, что он использует регулярные выражения, но меня смущает "$ 1.reverse, $ 2"

def commify(n)
  n.to_s =~ /([^\.]*)(\..*)?/
  int, dec = $1.reverse, $2 ? $2 : ""
  while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
  end
  int.reverse + dec
end

Может кто-нибудь объяснить, что происходит в этом коде?

Ответы [ 3 ]

5 голосов
/ 13 сентября 2010

$1, $2, $3 ... являются наследием Perl.Это переменные группы захвата , то есть они захватывают группы внутри регулярного выражения.

Именованная группа указывается в скобках.Итак, первая группа захвата соответствует ([^\.]), то есть любому не точечному символу, а (\..*) соответствует точечному символу \. и любым другим символам после него.

Обратите внимание, что вторая группа является необязательной, поэтому в строке ниже у вас есть троичное выражение $2 ? $2 : "", которое является загадочным способом получить либо значение захвата пустой строки.

int, dec = $1, $2_or_blank_string - это параллельное присваивание .Ruby поддерживает назначение более чем одной переменной одновременно, это не отличается от выполнения int = $1.reversed, затем dec = $2 Так что int теперь содержит целую часть (в обратном порядке) и dec десятичную часть числа.Нас сейчас интересует первая.

Следующая пустая while выполняет подстановку строки.Метод gsub! заменяет все вхождения регулярного выражения на значение в аргументе secondf.Но он возвращает nil, если никаких изменений не произошло, что завершает while.

Выражение /(,|\.|^)(\d{3})(\d)/ соответствует:

  1. (,|\.|^) Запятая, точка илиначало строки
  2. (\d{3}) Три цифры
  3. (\d) Четвертая цифра

Затем она заменяется на \1\2,\3.\n в подстановке строк означает n-ю группу захвата, как и переменные $n.Итак, в основном это так: если у меня четыре цифры, просто добавьте запятую после третьей.Повторяйте до тех пор, пока группа из четырех цифр не будет найдена

Затем просто снова переверните целую часть и добавьте десятичную часть.

5 голосов
/ 13 сентября 2010

n.to_s =~ /([^\.]*)(\..*)?/ принимает число в виде строки и сохраняет все до десятичной точки (или просто все, если нет десятичной точки) в $1 и все после, включая его в $2.

int, dec = $1.reverse, $2 ? $2 : "" сохраняет обратное значение $1 в int и $2 или "", если $2 равно nil, в dec.Другими словами, int теперь содержит часть перед обращенной десятичной точкой, а dec содержит часть после точки (не обращенной).

Следующая строка вставляет запятую через каждые три места в int.Поэтому, снова поменяв int, мы получим исходную неотъемлемую часть числа с запятыми, вставленными через каждые три места с конца.Теперь мы снова добавляем dec в конце и получаем правильные числа с запятыми в нужных местах.

3 голосов
/ 13 сентября 2010

Другой способ:

class Integer
  def commify
    self.to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,')
  end
end

Тогда вы можете сделать 12345678.commify и получить строку 12,345,678

А вот тот, который обрабатывает числа с плавающей запятой:

class Float
  def commify
    self.to_s.reverse.gsub(/(\d\d\d)(?=\d)(?!\d*\.)/,'\1,').reverse
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...