在 Ruby 中,我可以在不使用正则表达式的情况下检查字符串是不是包含字母吗?

Posted

技术标签:

【中文标题】在 Ruby 中,我可以在不使用正则表达式的情况下检查字符串是不是包含字母吗?【英文标题】:In Ruby, can I check if a string contains a letter without using regular expressions?在 Ruby 中,我可以在不使用正则表达式的情况下检查字符串是否包含字母吗? 【发布时间】:2017-05-23 00:31:22 【问题描述】:

我正在使用 Rails 5。我想知道一个变量(你可以假设它是一个字符串)是否包含至少一个字母(大写或小写)。但是,我不想使用正则表达式(我注意到如果编码不是 UTF-8,正则表达式往往会崩溃)。所以我想知道如何检查一个字符串是否至少包含一个字母。

这行不通

input.downcase.include?("abcdefghijklmnopqrstuvwxyz")

【问题讨论】:

你有一个具体的例子,非 UTF8 字符串的正则表达式失败? “ö”是字母吗? “ç”是字母吗? “я”是字母吗? @mudasobwa :看起来不是这样,Natalia 提供了一个可接受的字符字符串。 Natalia,当可能出现非 ASCII 字符时,您可以使用 str =~ /[[:alpha:]]/str =~ /\pAlpha/。在Regexp 中搜索“POSIX”和“字符属性”。 他们很可能得到ArgumentError: invalid byte sequence in US-ASCII,这是 Ruby 中正则表达式的一个非常烦人的行为。 【参考方案1】:

试试这个

str.count("a-zA-Z") > 0

count function 接受字符集作为参数。

不过,ArgumentError: invalid byte sequence in UTF-8 可能仍然会失败。如果您的输入无效,则可能无法修复编码。

注意,这会扫描整个字符串,但downcase 也是如此。对于性能基准,请参阅 Eric 的回答,性能在最坏情况和最佳情况之间变化很大。不过,与往常一样,可读性先于过早的优化。

【讨论】:

很好,已修复! 它确实有一个缺点,就是计算一个可能很大的字符串中的所有字母,只是为了检查是否至少有 1 个。 老实说,让我补充一点——尽管提前休息和全面扫描具有“完全相同的复杂性”,只是说:) 如果您考虑到平均和最坏情况的复杂性,则不会。您的解决方案确实具有将最坏情况作为平均值的优势;)。 "这是最快的方法" Citation needed【参考方案2】:

代码

你可以使用:

lowercase = ('a'..'z')
uppercase = ('A'..'Z')
input.each_char.any? |char| lowercase.cover?(char) || uppercase.cover?(char) 

它使用Range#cover?,比Range#include? 更快,因为它只检查char >= 'a'char <= 'z'

性能

在最坏的情况下(没有字母 "1#+~?5()=[" * 10_000 的巨大字符串):

Running each test 8 times. Test will take about 9 seconds.
_akuhn is faster than _mudasobwa by 2.0x ± 0.01
_mudasobwa is faster than _cary by 14x ± 0.1
_cary is faster than _eric_duminil by 10.5x ± 0.1

带有 mp3 文件的尾部(600kb):

Running each test 2048 times. Test will take about 7 minutes.
_cary is faster than _eric_duminil by 12x ± 1.0
_eric_duminil is faster than _mudasobwa by 430x ± 10.0
_mudasobwa is faster than _akuhn by 3x ± 0.1

有趣的是,结果差异如此之大。

【讨论】:

('a'..'z') 将在 Ruby 中创建 O(2n) 短期字符串,除非您使用冻结字符串文字编译指示。为什么?每次解释器遇到字符串文字时,它都会创建该文字的副本。 几乎不值得一提,但是(为了避免创建临时数组)我建议 each_char 后跟 Enumerable 方法。 @CarySwoveland:谢谢。你完全正确。我只是在进行基准测试,并注意到我的方法比 mudasobwa 慢 160 倍。 :D charseach_char 是相同的方法。它返回一个枚举器。 因为它被一根丑陋的棍子打了。请将str =~ /[[:alpha:]]/ 添加到您的基准测试中。【参考方案3】:
checker = lambda do |input|
  "abcdefghijklmnopqrstuvwxyz".split('').any? &input.downcase.method(:include?)
end

checker.('3F3')
#⇒ true
checker.('42')
#⇒ false

【讨论】:

您真的需要拨打downcase 26 次吗? : @EricDuminil 它仍然比在 1MB 字符串上调用 include? 1M 次要好,有一个最后一个字母:) 真的有影响吗?我想说我们的方法具有完全相同的复杂性。我们有一个include? 的矩阵,你用行,我用列。 @EricDuminil 确实。

以上是关于在 Ruby 中,我可以在不使用正则表达式的情况下检查字符串是不是包含字母吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不编写正则表达式的情况下从字符串中解析日期?

在不使用正则表达式的情况下,在NSString中计算单词数量的最有效方法是什么?

在不使用正则表达式的情况下,判断一个字符是 Java 中的字母还是数字的最佳方法是啥?

如何在不使用 Ruby 保存到磁盘的情况下生成 zip 文件?

在没有正则表达式的情况下验证具有不同格式的电话号码

在不阻止谷歌驱动器的情况下阻止 youtube