如何在 Ruby 中指定范围

How to specify a range in Ruby

我一直在寻找一种好方法来查看一串项目是否都是数字,并且认为可能有一种方法可以指定从 0 到 9 的范围并查看它们是否包含在字符串中, 但是我在网上查的所有这些都让我很困惑。

def validate_pin(pin)
  (pin.length == 4 || pin.length == 6) && pin.count("0-9") == pin.length
end

上面的代码是别人的作品,我一直在尝试确定它是如何工作的。这是一个 pin 检查器 - 接受一组字符并确保字符串是 4 位或 6 位数字和所有数字 - 但范围如何工作?

当我做这个问题时我尝试使用to_a?整数和一堆其他东西,包括范围,例如 (0..9) 和 ("0..9) 和 ("0".."9") 来验证一个字符是一个整数。当我看到 ("0 -9) 它把我弄糊涂了,半小时的谷歌搜索和 youtube 只给我留下了正则表达式教程(我对此很感兴趣,但目前只是想了解基础知识)

综上所述,我的目标是了解一种更 semantic/concise 的方法来识别字符是否为整数。无论哪种方式都是最简单的。欢迎所有反馈。我是一个新的 ruby​​ist 并试图降低我的基础知识。谢谢。

正则表达式确实是执行此操作的正确方法。它专门用于测试字符串中的模式。这就是您测试“此字符串中的所有字符是否都在字符 0-9 范围内吗?”的方式:

pin.match(/\A[0-9]+\z/)

此正则表达式表示“此字符串是否至少以字符 0-9 之一开始和结束,中间没有其他字符?” - \A 和 \z 是字符串开头和结尾匹配器,[0-9]+ 匹配该范围内的任意一个或多个字符。

您甚至可以在一行正则表达式中完成整个检查:

pin.match(/\A([0-9]{4}|[0-9]{6})\z/)

这表示“此字符串是由正好重复 4 次的字符 0-9 组成,还是由正好重复 6 次的字符 0-9 组成?”

Ruby 的 String#count method 做了类似的事情,虽然它只是计算传递的字符的出现次数,并且它使用类似于正则表达式范围的东西来允许你指定字符范围。

The sequence c1-c2 means all characters between c1 and c2.

因此,它将参数“0-9”扩展为字符列表“0123456789”,然后测试字符串中有多少字符与该字符列表匹配。

这将用于验证字符串中是否存在一定数量的数字,并且长度检查让您隐式测试字符串中不存在 other 个字符。但是,正则表达式可让您通过确保整个字符串匹配给定模式(包括长度限制)来直接断言。

由于您似乎在寻找正则表达式之外的答案,并且由于 Chris 已经在上面的示例中详细说明了如何实现计数方法,所以我将尝试添加一个想法来测试字符串是否为整数与否:

pin.to_i.to_s == pin

我们正在做的是将字符串转换为整数,将结果转换回字符串,然后进行测试以查看在此过程中是否有任何变化。如果结果是 =>true,那么您知道在转换为整数期间没有任何变化,因此字符串只是一个整数。

编辑: 上面的示例仅在整个字符串为 Integer 且无法正确处理前导零时才有效。如果您想检查以确保每个字符都是整数,那么请改为执行以下操作:

pin.prepend(“1”).to_i.to_s(1..-1) == pin

计算 pin 中的所有非数字并检查此计数是否为零:

pin.count("^0-9").zero?

部分问题似乎是以下代码部分是如何完成工作的:

pin.count("0-9")

这段代码只是返回字符串中存在的数字 0 到 9 的实例数。不过,这只是相关代码部分的一部分。您需要查看该行的其余部分才能理解它:

pin.count("0-9") == pin.length

第一部分计算实例的数量,然后第二部分将其与字符串的长度进行比较。如果它们相等 (==) 则意味着字符串中的每个字符都是整数。

有时候否定也可以变成优势:

!pin.match?(/\D/) && [4,6].include?(pin.length)

pin.match?(/\D/) returns true 如果字符串包含数字以外的字符(匹配 /\D/),在这种情况下它将取反为 false.

这里使用否定的一个好处是,如果字符串包含数字以外的字符,pin.match?(/\D/) 将在找到非数字后立即 return true,因为与检查字符串中所有字符的方法相反。