Неплохо. В Ruby вы обычно опускаете ключевое слово «return», если возвращаемое значение генерируется в последнем выражении функции. Это также вернет целочисленное значение, равное нулю, вы, вероятно, захотите логическое значение, поэтому что-то вроде !! (str = ~ / ^ [- +]? [0-9] + $ /) сделает это. Затем вы можете добавить его в String и опустить аргумент, используя «self» вместо «str», а затем вы можете изменить имя на «is_i?» ...
janm 05
2
Спасибо! Я понятия не имею о правилах и правилах использования Ruby. Я просто быстро погуглил по Ruby и регулярным выражениям, чтобы увидеть синтаксис, изменил регулярное выражение, чтобы применить к рассматриваемой проблеме, и протестировал его. На самом деле он довольно изящный ... Возможно, мне придется присмотреться к нему, когда у меня будет больше свободного времени.
Rado
У вас есть правильная идея, но она не соответствует двоичным или шестнадцатеричным литералам (см. Мое отредактированное решение ниже).
Сара Мей
16
Два комментария. Можно использовать /regexp/ === selfвместо !!(self =~ /regexp/)конструкции. Вы можете использовать класс символов «\ d» вместо[0-9]
которым
1
Самым простым регулярным выражением для целого числа, вероятно, является / ^ \ d + $ /
Я не согласен с решениями, которые вызывают исключение для преобразования строки - исключения не являются потоком управления, и вы также можете сделать это правильно. Тем не менее, мое вышеприведенное решение не касается целых чисел, отличных от десятичной. Итак, вот способ обойтись, не прибегая к исключениям:
classStringdef integer?[# In descending order of likeliness:/^[-+]?[1-9]([0-9]*)?$/,# decimal/^0[0-7]+$/,# octal/^0x[0-9A-Fa-f]+$/,# hexadecimal/^0b[01]+$/# binary].each do|match_pattern|returntrueifself=~ match_patternendreturnfalseendend
Не могли бы вы заменить self.to_i.to_s == selfна Integer self rescue false?
Мередит Л. Паттерсон
5
Можно, но это было бы дурным тоном. Вы не используете исключения в качестве потока управления, и ни один код никогда не должен содержать «rescue false» (или «rescue true»). Некоторый простой gsub'ing заставил бы мое решение работать для крайних случаев, не указанных OP.
Сара Мей
4
Я знаю, что многие люди его используют, и это, безусловно, эстетично. Для меня это признак того, что код нуждается в реструктуризации. Если вы ожидаете исключения ... это не исключение.
Сара Мей
2
Я согласен с тем, что исключения не следует использовать в качестве потока управления. Я не думаю, что требуется признание номеров, ориентированных на разработчиков. В ситуациях, не связанных с программированием, это можно рассматривать как ошибку, особенно с учетом возможной путаницы с начальными нулями и восьмеричными числами. Также не соответствует to_i. Ваш код не обрабатывает случай «-0123». Как только вы справитесь с этим случаем, вам не понадобится отдельное регулярное выражение для восьмеричного. Вы можете просто продолжить, используя «любой?». Единственным оператором в вашей функции может быть "[/ re1 /, / re2 /, / re3 /] .any? {| Re | self = ~ re}", без предложений if или возвратов.
janm 06
67
Вы можете использовать Integer(str)и посмотреть, поднимается ли он:
Следует отметить, что, хотя это действительно возвращает true для "01", это не для "09", просто потому, 09что не будет действительным целочисленным литералом. Если это не то поведение, которое вам нужно, вы можете добавить его 10в качестве второго аргумента Integer, чтобы число всегда интерпретировалось как основание 10.
Чувак ... провоцируешь исключение только для преобразования числа? Исключения - это не поток управления.
Сара Мей
29
Это не так, но, к сожалению, это канонический способ определения «целочисленности» строки в Ruby. Методы использования #to_iслишком ломаются из-за своей вседозволенности.
Avdi
17
Для тех, кто задается вопросом, почему, Целое число («09») недействительно, потому что «0» делает его восьмеричным, а 9 - недопустимым восьмеричным числом. osdir.com/ml/lang.ruby.general/2002-08/msg00247.html
Эндрю Гримм,
20
Сара: вы можете использовать регулярное выражение, но для обработки всех случаев, которые делает Ruby при разборе целых чисел (отрицательные числа, шестнадцатеричные, восьмеричные, знаки подчеркивания, например, 1_000_000), это будет очень большое регулярное выражение, и легко ошибиться. Integer()является каноническим, потому что Integer ()вы точно знаете, что все, что Ruby считает целочисленным литералом, будет принято, а все остальное будет отклонено. Дублирование того, что уже дает вам язык, - возможно, худший запах кода, чем использование исключений для контроля.
Avdi
9
@Rado So изобретает велосипед.
sepp2k
24
Вы можете сделать один лайнер:
str =...
int =Integer(str)rescuenilif int
int.times {|i| p i}end
или даже
int =Integer(str)rescuefalse
В зависимости от того, что вы пытаетесь сделать, вы также можете напрямую использовать начальный конечный блок с предложением rescue:
begin
str =...
i =Integer(str)
i.times do|j|
puts j
endrescueArgumentError
puts "Not an int, doing something else"end
Что касается темы «исключение как поток управления»: поскольку мы не знаем, как использовать рассматриваемый метод, мы не можем судить, подходят ли исключения или нет. Если строка вводится и должна быть целым числом, то предоставление нецелого числа потребует исключения. Хотя тогда, возможно, обработка не в том же методе, и мы, вероятно, просто будем использовать Integer (str) .times {| i | помещает i} или что-то еще.
Он не возвращается, trueа falseтолько MatchDataэкземпляры иnil
Стефан
Это не то, что он возвращает, но если оно совпадает,
Мацей Красовски
5
Оберните его !!или используйте, present?если вам нужно логическое значение !!( "12".match /^(\d)+$/ )или "12".match(/^(\d)+$/).present?(последнее требует Rails / activesupport)
mahemoff
1
Это регулярное выражение не принимает во внимание знак: отрицательные числа также являются действительными целыми числами . Теперь вы проверяете действительные натуральные числа или ноль.
Йохем Шуленклоппер,
13
Ruby 2.6.0 разрешает приведение к целому числу без возникновения исключения и вернется, nilесли приведение завершится неудачно. И поскольку в nilосновном ведет себя как falseв Ruby, вы можете легко проверить целое число следующим образом:
ifInteger(my_var, exception:false)# do something if my_var can be cast to an integerend
+1 за имя #integer ?, -1 за загромождение String им :-P
Avdi
1
Куда еще оно могло пойти? integer?("a string")FTL.
Август Лиллеа, 05
2
String#integer?это своего рода общий патч, который каждый Ruby-программист и его двоюродный брат любят добавлять в язык, что приводит к кодовым базам с тремя различными слегка несовместимыми реализациями и неожиданным сбоям. Я усвоил это на собственном горьком опыте на больших проектах Ruby.
Avdi
Тот же комментарий, что и выше: исключения не должны использоваться для потока управления.
Сара Мей
Оборотная сторона: это решение приводит к потере одной конверсии.
Роберт Клемме
7
Самый лучший и простой способ - использовать Float
val =Float"234"rescuenilFloat"234"rescuenil#=> 234.0Float"abc"rescuenil#=> nilFloat"234abc"rescuenil#=> nilFloatnilrescuenil#=> nilFloat""rescuenil#=> nil
Integerтакже хорошо , но он вернется 0кInteger nil
Ответы только на код не очень полезны. Вместо этого объясните, как это работает и почему это правильный ответ. Мы хотим просвещать нас в будущем, чтобы решение было понятным, а не непосредственный вопрос.
Железный Человек
3
Лично мне нравится подход с исключениями, хотя я бы сделал его немного короче:
Для более старых версий Ruby существует Regexp#===. И хотя прямого использования оператора равенства case следует избегать, здесь он выглядит очень чисто:
/^(\d)+$/является регулярным выражением выражения для поиска цифр в любой строке. Вы можете проверить свои регулярные выражения и результаты на http://rubular.com/ .
Мы сохраняем его в константе, IntegerRegexчтобы избежать ненужного выделения памяти каждый раз, когда мы используем его в методе.
integer?- это вопросительный метод, который должен возвращать trueили false.
match - это метод для строки, который сопоставляет вхождения в соответствии с заданным выражением регулярного выражения в аргументе и возвращает сопоставленные значения или nil .
!!преобразует результат matchметода в эквивалентное логическое значение.
А объявление метода в существующем Stringклассе - это исправление обезьяны, которое ничего не меняет в существующих функциях String, а просто добавляет другой метод, названный integer?для любого объекта String.
Не могли бы вы добавить к этому небольшое пояснение?
Стеф
@stef - я сделал то же самое. Пожалуйста, дайте мне знать, если у вас все еще есть вопросы.
Sachin
1
Расширяя ответ @rado выше, можно также использовать тернарный оператор для принудительного возврата истинных или ложных логических значений без использования двойного удара. Конечно, версия с двойным логическим отрицанием более лаконична, но, вероятно, труднее читать новичкам (например, мне).
Учтите, что использование регулярных выражений заставляет Ruby выполнять гораздо больше работы, поэтому, если это используется в цикле, это замедлит код. Привязка выражения помогает, но регулярное выражение все еще значительно медленнее.
Железный Человек
1
Для более общих случаев (включая числа с десятичной точкой) вы можете попробовать следующий метод:
Вызывать не обязательно, obj.is_a? Stringпотому что String # to_s вернет сам себя, что, я думаю, не требует слишком большой обработки по сравнению с .is_a?вызовом. Таким образом, вы будете делать только один звонок в этой линии вместо одного или двух. Кроме того, вы можете включить его непосредственно !!в number?метод, поскольку по соглашению имя метода, которое заканчивается на ?, должно возвращать логическое значение. С уважением!
Это не то, что задает исходный вопрос. OP также хочет знать, является ли строка целым числом. например "12".is_an_integer? == true"not12".is_an_integer? == false12.is_an_integer? == true
Ответы:
Вы можете использовать регулярные выражения. Вот функция с предложениями @janm.
Отредактированная версия согласно комментарию @wich:
Если вам нужно проверить только положительные числа
источник
/regexp/ === self
вместо!!(self =~ /regexp/)
конструкции. Вы можете использовать класс символов «\ d» вместо[0-9]
Что ж, вот простой способ:
Я не согласен с решениями, которые вызывают исключение для преобразования строки - исключения не являются потоком управления, и вы также можете сделать это правильно. Тем не менее, мое вышеприведенное решение не касается целых чисел, отличных от десятичной. Итак, вот способ обойтись, не прибегая к исключениям:
источник
self.to_i.to_s == self
наInteger self rescue false
?Вы можете использовать
Integer(str)
и посмотреть, поднимается ли он:Следует отметить, что, хотя это действительно возвращает true для
"01"
, это не для"09"
, просто потому,09
что не будет действительным целочисленным литералом. Если это не то поведение, которое вам нужно, вы можете добавить его10
в качестве второго аргументаInteger
, чтобы число всегда интерпретировалось как основание 10.источник
#to_i
слишком ломаются из-за своей вседозволенности.Integer()
является каноническим, потому чтоInteger ()
вы точно знаете, что все, что Ruby считает целочисленным литералом, будет принято, а все остальное будет отклонено. Дублирование того, что уже дает вам язык, - возможно, худший запах кода, чем использование исключений для контроля.Вы можете сделать один лайнер:
или даже
В зависимости от того, что вы пытаетесь сделать, вы также можете напрямую использовать начальный конечный блок с предложением rescue:
источник
источник
true
аfalse
толькоMatchData
экземпляры иnil
!!
или используйте,present?
если вам нужно логическое значение!!( "12".match /^(\d)+$/ )
или"12".match(/^(\d)+$/).present?
(последнее требует Rails / activesupport)Ruby 2.6.0 разрешает приведение к целому числу без возникновения исключения и вернется,
nil
если приведение завершится неудачно. И поскольку вnil
основном ведет себя какfalse
в Ruby, вы можете легко проверить целое число следующим образом:источник
is_
. Я нахожу это глупым в методах вопросительного знака, мне нравится"04".integer?
намного больше, чем"foo".is_integer?
."01"
и тому подобное.источник
integer?("a string")
FTL.String#integer?
это своего рода общий патч, который каждый Ruby-программист и его двоюродный брат любят добавлять в язык, что приводит к кодовым базам с тремя различными слегка несовместимыми реализациями и неожиданным сбоям. Я усвоил это на собственном горьком опыте на больших проектах Ruby.Самый лучший и простой способ - использовать
Float
Integer
также хорошо , но он вернется0
кInteger nil
источник
Я предпочитаю:
конфиг / Инициализаторы / string.rb
а потом:
или проверьте номер телефона:
источник
Более простой способ мог бы быть
источник
источник
Лично мне нравится подход с исключениями, хотя я бы сделал его немного короче:
Однако, как уже говорили другие, это не работает с восьмеричными строками.
источник
Ruby 2.4 имеет
Regexp#match?
: (с?
)Для более старых версий Ruby существует
Regexp#===
. И хотя прямого использования оператора равенства case следует избегать, здесь он выглядит очень чисто:источник
Это может не подходить для всех случаев, просто используя:
может также подойти для некоторых.
Если это число, а не 0, он вернет число. Если он возвращает 0, это либо строка, либо 0.
источник
"12blah".to_i => 12
. Это может вызвать некоторые проблемы в необычных сценариях.Вот мое решение:
А вот как это работает:
/^(\d)+$/
является регулярным выражением выражения для поиска цифр в любой строке. Вы можете проверить свои регулярные выражения и результаты на http://rubular.com/ .IntegerRegex
чтобы избежать ненужного выделения памяти каждый раз, когда мы используем его в методе.integer?
- это вопросительный метод, который должен возвращатьtrue
илиfalse
.match
- это метод для строки, который сопоставляет вхождения в соответствии с заданным выражением регулярного выражения в аргументе и возвращает сопоставленные значения илиnil
.!!
преобразует результатmatch
метода в эквивалентное логическое значение.String
классе - это исправление обезьяны, которое ничего не меняет в существующих функциях String, а просто добавляет другой метод, названныйinteger?
для любого объекта String.источник
Расширяя ответ @rado выше, можно также использовать тернарный оператор для принудительного возврата истинных или ложных логических значений без использования двойного удара. Конечно, версия с двойным логическим отрицанием более лаконична, но, вероятно, труднее читать новичкам (например, мне).
источник
Для более общих случаев (включая числа с десятичной точкой) вы можете попробовать следующий метод:
Вы можете протестировать этот метод в сеансе irb:
Подробное объяснение задействованного здесь регулярного выражения можно найти в этой статье блога :)
источник
obj.is_a? String
потому что String # to_s вернет сам себя, что, я думаю, не требует слишком большой обработки по сравнению с.is_a?
вызовом. Таким образом, вы будете делать только один звонок в этой линии вместо одного или двух. Кроме того, вы можете включить его непосредственно!!
вnumber?
метод, поскольку по соглашению имя метода, которое заканчивается на?
, должно возвращать логическое значение. С уважением!Мне нравится следующее:
Но осторожно:
источник
Один лайнер в
string.rb
источник
Я не уверен, было ли это когда-то, когда задают этот вопрос, но для всех, кто наткнется на этот пост, самый простой способ:
.is_a?
будет работать с любым объектом.источник
"12".is_an_integer? == true
"not12".is_an_integer? == false
12.is_an_integer? == true