Regex 使用类正则表达式条件生成字符串
我想知道实现满足以下二次思考要求的最佳字符串生成器类是否可行:Regex 使用类正则表达式条件生成字符串,regex,string,delphi,generator,enumerator,Regex,String,Delphi,Generator,Enumerator,我想知道实现满足以下二次思考要求的最佳字符串生成器类是否可行: 生成标准使用 枚举 计数属性 索引访问 我对正则表达式感到不舒服:我无法给出一段起始代码,但我只想到了一个简单的实现,它使用TList作为基类,并对“暴力”生成的字符串使用过滤器(Regex) 其他最佳选择是什么? 排序:先按长度排序(最短优先),然后按字典排序 生成中要使用的字符范围的规范:所有可打印字符或[A-Z]、[A-Z]、数字、特殊符号和最终空格(regex?)的任何可能组合 以给定的最小值/最大值为界的字符
- 生成标准使用
- 枚举
- 计数属性
- 索引访问
- 排序:先按长度排序(最短优先),然后按字典排序
- 生成中要使用的字符范围的规范:所有可打印字符或[A-Z]、[A-Z]、数字、特殊符号和最终空格(regex?)的任何可能组合
- 以给定的最小值/最大值为界的字符串长度
- 受边界约束的搜索空间:开始字符串可能进行筛选的结束字符串(regex?)
上次编辑 首先,我用regex-like而不是regex重新表述了标题 我正在考虑修改第一个要求,因为这是一个敞开的大门,可能导致无法执行的问题 我需要正确措辞的建议和帮助
第二个想法完成了。仍然可以提出改进建议。老问题,但没有人回答,悬赏仍然有效,我已经准备好了解决方案,所以这里有一个可能的答案: 我曾经写过一篇这样的文章。然而,它在C++/Qt中(虽然我几乎所有的程序都是用Delphi编写的,但其中一个是用C++)不支持Unicode,并且没有顺序保证 其工作原理如下:
[a-c]+[a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c]成为[a-c][ttt][ttt][ttt][ttt][ttt][a-t][t][a-t][t][t][a-c][a-c][t][a-
(后一个表达式中的|只是表示法,程序在列表中保留每个备选子类)
[a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c]|t | tt | tt | ttt |([x-z])foo\1\2 | at | au | bt bu
现在,每个备选子项匹配一个固定长度的字符串
a | b | c | aa | ba | cc | aaa | ccc | aaaa | cccc | t | tt | ttt | xxfoox | yxfooyx | zzfoozz at | au | bt code>
我会通过构造语言的最小值来实现这一点。如果您从正则表达式开始,这可以通过Thompson构造自动完成,然后是子集构造和最小化。例如,见 有了DFA,您可以使用如下算法:
Let P = { < START, [""] > } be a set of pairs <State, list of strings>
for n = 0, 1, ... Max
Let P' = {} be a new set
while P is not empty
Remove the pair <s, L> from P
For each transition s -- c --> t in alpha order of c
if t is an accepting state,
output l + c for each string l in L
put <t, L + c> in P' (** i.e. append c to each string in L)
end
Set P = P'
end
由于不熟悉德尔菲,我只能从一个总体的观点来发言。在我看来,最好的方法是将正则表达式解析成一个表示其等价状态机的图(维基百科应该能够为您指出正确的方向)。从那里,可以通过对所述图形执行深度优先遍历来生成单词(当然要记住,它很可能是循环的)。这里的缺点是我们不能利用内置于regex支持的语言。+1:非常有趣。这是一种真正的生成方法,与我高度低效的生成器/测试方法相反。在我看来,这根本没有坏处:内置的regex支持用于评估,这会误导我设计解决方案。你可以考虑迁移你的评论作为答案,我觉得它是可以接受的。谢谢。这似乎是一种使用正则表达式的愚蠢方式。我认为生成生成器对象的简化生成器表达式系统可能有点类似于某些正则表达式功能(支持
[a-Z]。
和[a-Z]*
(在固定限制内)单独使用就足够了。通配符确实为生成字符串提供了一个有趣的问题。例如,第一个字符串是什么(按字典顺序排列)这可以由<代码> A*B<代码>产生吗?考虑<代码> AB <代码>之前>代码> B<代码>,<代码> AAB <代码> >代码> Ab>代码>等。我们可以归纳出第一个字符串是一个无限重复的<代码> A<代码>,后面是一个单一的<代码> B<代码>。显然我们不能表示这一点,因此我们必须设置一个固定的。(即任意)l
import java.util.Comparator;
import java.util.TreeSet;
public class Test{
public static class DFA {
public static class Transition {
final int to;
final char lo, hi; // Character range.
public Transition(int to, char lo, char hi) {
this.to = to;
this.lo = lo;
this.hi = hi;
}
public Transition(int to, char ch) {
this(to, ch, ch);
}
}
// transitions[i] is a vector of transitions from state i.
final Transition [] [] transitions;
// accepting[i] is true iff state i is accepting
final boolean [] accepting;
// Make a fresh immutable DFA.
public DFA(Transition [] [] transitions, boolean [] accepting) {
this.transitions = transitions;
this.accepting = accepting;
}
// A pair is a DFA state number and the input string read to get there.
private static class Pair {
final int at;
final String s;
Pair(int at, String s) {
this.at = at;
this.s = s;
}
}
// Compare pairs ignoring `at` states, since
// they are equal iff the strings are equal.
private Comparator<Pair> emitOrder = new Comparator<Pair>() {
@Override
public int compare(Pair a, Pair b) {
return a.s.compareTo(b.s);
}
};
// Emit all strings accepted by the DFA of given max length.
// Output is in sorted order.
void emit(int maxLength) {
TreeSet<Pair> pairs = new TreeSet<Pair>(emitOrder);
pairs.add(new Pair(0, ""));
for (int len = 0; len <= maxLength; ++len) {
TreeSet<Pair> newPairs = new TreeSet<Pair>(emitOrder);
while (!pairs.isEmpty()) {
Pair pair = pairs.pollFirst();
for (Transition x : transitions[pair.at]) {
for (char ch = x.lo; ch <= x.hi; ch++) {
String s = pair.s + ch;
if (newPairs.add(new Pair(x.to, s)) && accepting[x.to]) {
System.out.println(s);
}
}
}
}
pairs = newPairs;
}
}
}
// Emit with a little DFA for floating point numbers.
public void run() {
DFA.Transition [] [] transitions = {
{ // From 0
new DFA.Transition(1, '-'),
new DFA.Transition(2, '.'),
new DFA.Transition(3, '0', '1'),
},
{ // From 1
new DFA.Transition(2, '.'),
new DFA.Transition(3, '0', '1'),
},
{ // From 2
new DFA.Transition(4, '0', '1'),
},
{ // From 3
new DFA.Transition(3, '0', '1'),
new DFA.Transition(4, '.'),
},
{ // From 4
new DFA.Transition(4, '0', '1'),
}
};
boolean [] accepting = { false, false, false, true, true };
new DFA(transitions, accepting).emit(4);
}
public static void main (String [] args) {
new Test().run();
}
}