在另一个问题中,我学会了如何使用正则表达式计算直接扑克牌(here)。
现在,出于好奇,问题是:我可以使用正则表达式使用ASCII代码计算相同的东西吗?
类似的东西:
正则表达式:[C] [C + 1] [C + 2] [C + 3] [C + 4],是C的ASCII码(或者像这样)
匹配:45678
,23456
不匹配:45679
或23459
(不按顺序)
答案 0 :(得分:5)
你的主要问题实际上是你手上没有使用ASCII连续编码,你使用非面部卡的数字,以及面部卡的非连续,无序字符。< / p>
您需要在字符串的开头检测2345A, 23456, 34567, ..., 6789T, 789TJ, 89TJQ, 9TJQK
和TJQKA
。
这些不是连续的ASCII码,即使它们是,也会遇到问题,因为A2345
和TJQKA
都有效,你不会得到{ {1}}小于和大于同一字符集中的其他字符。
如果 由正则表达式完成,那么以下正则表达式段:
A
可能是最简单,最易读的。
答案 1 :(得分:4)
正如其他答案所指出的那样,没有正则表达式可以做你想要的,但你确实说过你想要学习正则表达式,所以这里是另一种可能是教学的元正则表达式方法
这是一个Java片段,给定一个字符串,以编程方式生成将匹配该长度为5的字符串的任何子字符串的模式。
String seq = "ABCDEFGHIJKLMNOP";
System.out.printf("^(%s)$",
seq.replaceAll(
"(?=(.{5}).).",
"$1|"
)
);
输出为(as seen on ideone.com):
^(ABCDE|BCDEF|CDEFG|DEFGH|EFGHI|FGHIJ|GHIJK|HIJKL|IJKLM|JKLMN|KLMNO|LMNOP)$
通过适当初始化seq
,您可以使用它来方便地生成正则表达式模式以匹配直接的扑克牌。
.
元字符matches "any" character(行分隔符可能是个例外,具体取决于我们所处的模式)。
{5}
是一个精确的repetition说明符。 .{5}
完全匹配5 .
。
(?=…)
是positive lookahead;它断言给定的模式可以匹配,但由于它只是一个断言,它实际上并没有从输入字符串中产生(即消耗)匹配。
简单地(…)
是capturing group。它会创建一个后向引用,您可以在模式中稍后使用,或者在替换中使用,或者您认为合适。
为方便起见,此处重复此模式:
match one char
at a time
|
(?=(.{5}).).
\_________/
must be able to see 6 chars ahead
(capture the first 5)
该模式通过一次匹配一个字符.
来工作。然而,在匹配该字符之前,我们断言(?=…)
我们可以看到前面共有6个字符(.{5}).
,将(…)
捕获到第1组.{5}
中。对于每个这样的匹配,我们用$1|
替换,即组1捕获的任何内容,然后是交替元字符。
让我们考虑一下当我们将其应用于较短的String seq = "ABCDEFG";
时会发生什么。 ↑
表示我们当前的位置。
=== INPUT === === OUTPUT ===
A B C D E F G ABCDE|BCDEFG
↑
We can assert (?=(.{5}).), matching ABCDEF
in the lookahead. ABCDE is captured.
We now match A, and replace with ABCDE|
A B C D E F G ABCDE|BCDEF|CDEFG
↑
We can assert (?=(.{5}).), matching BCDEFG
in the lookahead. BCDEF is captured.
We now match B, and replace with BCDEF|
A B C D E F G ABCDE|BCDEF|CDEFG
↑
Can't assert (?=(.{5}).), skip forward
A B C D E F G ABCDE|BCDEF|CDEFG
↑
Can't assert (?=(.{5}).), skip forward
A B C D E F G ABCDE|BCDEF|CDEFG
↑
Can't assert (?=(.{5}).), skip forward
:
:
A B C D E F G ABCDE|BCDEF|CDEFG
↑
Can't assert (?=(.{5}).), and we are at
the end of the string, so we're done.
所以我们得到ABCDE|BCDEF|CDEFG
,这是seq
长度为5的所有子串。
答案 2 :(得分:3)
类似
regex: [C][C+1][C+2][C+3][C+4]
,C
ASCII代码(或类似内容)
在大多数正则表达式中,您无法远程执行任何操作。这根本不是正则表达式所设计的那种模式。
没有主流正则表达式模式可以匹配任何两个在ASCII编码中相差x
的连续字符。
String alpha = "ABCDEFGHIJKLMN";
String p = alpha.replaceAll(".(?=(.))", "$0(?=$1|\\$)|") + "$";
System.out.println(p);
// A(?=B|$)|B(?=C|$)|C(?=D|$)|D(?=E|$)|E(?=F|$)|F(?=G|$)|G(?=H|$)|
// H(?=I|$)|I(?=J|$)|J(?=K|$)|K(?=L|$)|L(?=M|$)|M(?=N|$)|N$
String p5 = String.format("(?:%s){5}", p);
String[] tests = {
"ABCDE", // true
"JKLMN", // true
"AAAAA", // false
"ABCDEFGH", // false
"ABCD", // false
"ACEGI", // false
"FGHIJ", // true
};
for (String test : tests) {
System.out.printf("[%s] : %s%n",
test,
test.matches(p5)
);
}
这使用元再生技术来生成模式。该模式使用lookahead确保每个字符后跟正确的字符(或字符串的结尾)。然后将该模式进行元正则化,重复匹配5次。
您可以根据需要将alpha
替换为您的扑克序列。
请注意,这是绝对不正确的解决方案。它的可读性更高,例如只需检查alpha.contains(test) && (test.length() == 5)
。
答案 3 :(得分:0)
<强>解决!强>
我在js中使用闭包解决了。
String.prototype.isSequence = function () {
If (this == "A2345") return true; // an exception
return this.replace(/(\w)(\w)(\w)(\w)(\w)/, function (a, g1, g2, g3, g4, g5) {
return code(g1) == code(g2) -1 &&
code(g2) == code(g3) -1 &&
code(g3) == code(g4) -1 &&
code(g4) == code(g5) -1;
})
};
function code(card){
switch(card){
case "T": return 58;
case "J": return 59;
case "Q": return 60;
case "K": return 61;
case "A": return 62;
default: return card.charCodeAt();
}
}
test("23456");
test("23444");
test("789TJ");
test("TJQKA");
test("8JQKA");
function test(cards) {
alert("cards " + cards + ": " + cards.isSequence())
}
只是为了澄清,ascii代码:
ASCII码:
2 = 50
3 = 51
4 = 52
5 = 53
6 = 54
7 = 55
8 = 56
9 = 57
T = 84 -> 58
J = 74 -> 59
Q = 81 -> 60
K = 75 -> 61
A = 65 -> 62