如何制作正则表达式以查看字符串是不是包含某个字母
Posted
技术标签:
【中文标题】如何制作正则表达式以查看字符串是不是包含某个字母【英文标题】:How to make a regex to see if string contains a certain letter如何制作正则表达式以查看字符串是否包含某个字母 【发布时间】:2013-12-23 02:03:05 【问题描述】:在一个网站上,我找到了“The quick brown fox jumps over the lazy dog”的一些替代方案,我决定编写一个小程序来检查替代方案是否有效。
对于那些有兴趣的人,我编写了以下程序(使用this post 的文件阅读器思想),它检查一个文件与彼此下方的句子:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TestClass
public static void main(String... aArgs)
TestClass tc = new TestClass();
try
String[] pieces = tc.splitFile("/home/user2609980/Desktop/text");
for (String line : pieces)
if (line.contains("a") &&
line.contains("b") &&
line.contains("c") &&
line.contains("d") &&
line.contains("e") &&
line.contains("f") &&
line.contains("g") &&
line.contains("h") &&
line.contains("i") &&
line.contains("j") &&
line.contains("k") &&
line.contains("l") &&
line.contains("m") &&
line.contains("n") &&
line.contains("o") &&
line.contains("p") &&
line.contains("q") &&
line.contains("r") &&
line.contains("s") &&
line.contains("t") &&
line.contains("u") &&
line.contains("v") &&
line.contains("w") &&
line.contains("x") &&
line.contains("y") &&
line.contains("z"))
System.out.println("Matches: " + line);
else
System.out.println("Does not match: " + line);
catch (Exception ex)
System.out.println(ex.getMessage());
public String[] splitFile(String file) throws IOException
BufferedReader br = new BufferedReader(new FileReader(file));
try
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null)
sb.append(line);
sb.append('\n');
line = br.readLine();
String everything = sb.toString();
String[] pieces = everything.split("\n");
return pieces;
finally
br.close();
这是输出:
Matches: The quick brown fox jumps over the lazy dog
Does not match: Pack my box with five dozen liquor jugs.
Matches: Several fabulous dixieland jazz groups played with quick tempo.
Does not match: Back in my quaint garden, jaunty zinnias vie with flaunting phlox.
Does not match: Five or six big jet planes zoomed quickly by the new tower.
Matches: Exploring the zoo, we saw every kangaroo jump and quite a few carried babies.
Matches: I quickly explained that many big jobs involve few hazards.
Does not match: Jay Wolf is quite an expert on the bass violin, guitar, dulcimer, ukulele and zither.
Matches: Expect skilled signwriters to use many jazzy, quaint old alphabets effectively.
Matches: The wizard quickly jinxed the gnomes before they vaporized.
我想从两个方面改进这个程序。一个,这是我的问题,是如何制作更有效的代码,而不是单独检查字母表中的每个字母。我怎样才能做出类似的东西:
line.Contains([regex])
如果可以的话?
额外的问题是我如何制作这个程序,以便它准确地打印出它不匹配的地方。当然我可以为每个字母做一个 if-else,但我希望有一个更漂亮的方法。
感谢您的关注,期待您的回复。
【问题讨论】:
请不要附赠问题,最好分开提问,这样对别人更有用 为什么Pack my box with five dozen liquor jugs.
不匹配?缺少什么字母?
确实...所以代码有问题。当然,我不匹配大写...
【参考方案1】:
我认为最简单的方法是使用这样的循环:
boolean allChars = true;
String uline = line.toUpperCase();
for (char c='A'; c<='Z'; c++)
if (uline.indexOf(c) < 0)
allChars = false;
break;
即运行从 65 (A) 到 90 (Z) 的循环,并检查输入字符串中是否存在每个字符。
【讨论】:
避免幻数。你可以使用for (char c='A'; c<='Z'; c++)
。
小写呢?
@Pshemo:谢谢,好主意,已编辑。 OP:我已经将输入全部转换为大写。
@user2609980:我已经添加了String uline = line.toUpperCase();
以首先将输入转换为全部大写。
@JuanMendes OP 代码中的整个条件都可以算作n
所以它也是O(n2)
【参考方案2】:
这是O(n)
的解决方案,它试图通过避免循环中的循环来加快速度。但是,性能测试表明,在这种情况下这样做并不值得。
请注意,当我假设您的代码是 O(n2)
时,我错了。它不是,即使你在一个循环中有一个循环。那是因为外部循环遍历一个常数(26 个字母)
Map<char, boolean> letters = new HashMap<String,boolean>
String uline = line.toUpperCase();
for (int i=0, i < uline.length; i++)
letters.put(uline.charAt(i), true );
boolean allChars = true;
for (char c='A'; c<='Z'; c++)
if (letters.get(c) == null)
allChars = false;
break;
如果您想要一个表示 AND 操作的正则表达式,您可以使用积极的前瞻断言来模仿它,but I have a feeling it's going to be slow。见https://***.com/a/470602/227299
(?=.*a)(?=.*b)(?=.*c)(?=.*d)(?=.*e)(?=.*f)(?=.*g)(?=.*h)(?=.*i)(?=.*j)(?=.*k)(?=.*l)(?=.*m)(?=.*n)(?=.*o)(?=.*p)(?=.*q)(?=.*r)(?=.*s)(?=.*t)(?=.*u)(?=.*v)(?=.*w)(?=.*x)(?=.*y)(?=.*z)
一定要使用不区分大小写的修饰符
在行动中看到它http://regex101.com/r/yJ4cU6
I created some performance tests 看看使用我建议的方法是否有意义,但事实并非如此。我会坚持阿努巴瓦的建议。希望答案能帮助您考虑性能(和过早优化)。
【讨论】:
你能解释一下你是O(n)
,而其他一些(我们必须避免)是O(n^2)
吗?大 O 表示法是什么意思以及如何(快速)计算它?
通常O(n2)
意味着你在一个循环中有一个循环,所以如果你的行是 100 个字符长(你的n
),它将需要 10,000 次比较。这种方法只会运行与字母一样多的比较,它会执行两次,一次是创建地图,一次是查看是否所有的字母都在里面。因此,对于相同的 100 个字符行,它会运行 200 次比较,而不是 100,000 次。这是一个很好的解释javacodegeeks.com/2011/04/simple-big-o-notation-post.html
啊。为什么你会说我的原始代码是 O(n)?我检查每一行中的每个字符与其他 26 个字符,这些字符将运行大约 26 倍的字母数量(O
)?为什么@anubavha的方法是O(n^2)?他基本上做同样的事情对吗? / 编辑感谢您的链接!
哦,我如何用函数式语言编写相同的东西,例如 Erlang?这似乎是一个很好的练习,我认为这样的东西会更漂亮。
@user2609980 是的,我弄错了,你和 anubhava 的代码都是 O(n),我的代码也是 O(n),但常数因子较低(2 而不是 26)。请注意,较低的常数最终并没有使其更快,可能是因为地图开销。查看我链接到的性能测试以上是关于如何制作正则表达式以查看字符串是不是包含某个字母的主要内容,如果未能解决你的问题,请参考以下文章
如何获得正则表达式来检查字符串是不是仅包含字母字符 [a-z] 或 [A-Z]?
求一个正则表达式: 以英文字母开头,只能包含英文字母、数字、下划线