English 中文(简体)
是否太缓慢? B. 真正的生活例子,如果简单、非常规的选择更好
原标题:Is regex too slow? Real life examples where simple non-regex alternative is better

我在这里看到的人发表了诸如“太慢”或“如果你使用“regex”这样简单的话。 (然后提出10+线路替代物),等等。

在工业环境中,我确实使用reg,因此,如果有人申请reg鱼太慢,那么我会很奇怪。 如果有“ple>非管制性替代物,则效果显著(甚至可能好!”)。

显然,许多高度专业化的操纵,采用复杂的扼杀算法,将很容易地超出常规,但我谈论存在简单解决办法的情况,并且<>显著><>优异>。

当然,什么是主观的,但我认为一个合理的标准是,如果它只使用<条码>、条码/条码>、<条码>、条码>、条码/条码等,则可能简单一些。


<说明><>>:我非常赞赏地回答如下:

  1. a beginner-level regex solution to a non-toy real-life problem that performs horribly
  2. the simple non-regex solution
  3. the expert-level regex rewrite that performs comparably
问题回答

我记得一本书记册,其中的reg子已经坏。 了解:建议采用以下方法生产! 用适当的CSV教区取代。

这一例子中的错误非常常见: 采用更窄的品级更合适。

在每一行各有12个ger子的CSV档案中,发现有13个处于第6位(无另外13个)。

1, 2, 3, 4, 5, 6, 7, 8 ,9 ,10,11,12 // don t match
42,12,13,12,32,13,14,43,56,31,78,10 // match
42,12,13,12,32,14,13,43,56,31,78,10 // don t match

我们使用一个含有准确11 com的reg子:

".*,.*,.*,.*,.*,13,.*,.*,.*,.*,.*,.*"

这样,每个“......*”仅限一个编号。 这一机制解决了这项任务,但业绩不佳。 (大约600台微秒在我的计算机上铺设,配对和校外相差不多。)

简单的非常规解决办法是:split(>,每一行各样,比较第6项内容。 (快速度:每秒9微秒)

监管局之所以如此缓慢,是因为“*”认证员因违约而处于贪.状态,因此,第一个“*”试图与整个扼杀相吻合,而后又开始按性质重现。 运行时间在计算线上的数字时成指数。

因此,我们用勉强的核素来取代贪 gr:

".*?,.*?,.*?,.*?,.*?,13,.*?,.*?,.*?,.*?,.*?,.*?"

这样做可以更好地进行相应的扼杀(系数为100),但对于非配对的扼杀几乎没有变化。

a. 履约者,以“[、]”性质类别取代胎盘:

"[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,13,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*"

(这需要3.7缩微秒,用于配对缝.,2.4用于我计算机上的无配方架。)

我试验了各种建筑的性能,但不幸的是,我发现,Java regex没有做我所认为的完全可以做的<>优化”。

Java regex takes O(N) to match "(?s)^.*+$"

这非常令人失望。 可在上查阅<>O(N),但最优化的“hints”(^<$)和单行模式Pattern.DOTALL/(?s),即使具有重复性(即没有背轨),reg发动机仍无法看到这种特性将符合每一条指示,并且仍然必须在>>。

当然,这种模式非常有用,但考虑到下一个问题。

Java regex takes O(N) to match "(?s)^A.*Z$"

同样,我希望,通过 anchor和单线模式,可以看到,这基本上与<条码>O(1)非管制性:

 s.startsWith("A") && s.endsWith("Z")

不幸的是,这还没有成为<条码>O(N)。 非常令人失望。 然而,由于存在冰冰和简单的非管制办法,这并不令人信服。

Java regex takes O(N) to match "(?s)^.*[aeiou]{3}$"

这种模式与3个下级传票相匹配。 别无选择和简单的非管制办法,但你仍然可以写出与这一点相呼应的内容,载于,因为你只需要检查最后3个特性(简而言之,我们可以假定,限制时间至少为3个)。

我还尝试了(?s)^.*$(?<=[aeiou]{3}),试图将 engine发动机仅仅忽略其他一切,只是检查最后3个特性,但当然这仍然是O(N)(见上文第一节)。

然而,在这一特定情况下,可以通过将其与<>代号>(<>>>/代码”相结合,使之有用。 这不是看整个插图是否与模式相符,而是你可以人工限制模式,只试图与最后的3个特性相匹配(>substring)。 总的来说,如果你事先知道该模式有限定的长度上限,你可以<编码>代号<>。 仅此刻,在一段很长的时间里,必须具备必要的特性。


Test harness

static void testAnchors() {
    String pattern = "(?s)^.*[aeiou]{3}$";
    for (int N = 1; N < 20; N++) {
        String needle = stringLength(1 << N) + "ooo";
        System.out.println(N);
        boolean b = true;
        for (int REPS = 10000; REPS --> 0; ) {
            b &= 
              needle
              //.substring(needle.length() - 3) // try with this
              .matches(pattern);
        }
        System.out.println(b);
    }
}

这一试验的强度大增。 如果你进行这一测试,你就会发现,它开始在<条码>10之后真正放慢(即显示时间1044)。 但是,如果你不赞同<代码>substring项目,整个测试将不时完成(这还证实,问题不是因为我没有使用<代码>Pattern.compile,这将产生最佳的不断改进,而是因为主食采用<代码>O(N)对等,在的征象增长成倍的情况下,这个问题就成问题。


Conclusion

看来,Java regex几乎没有根据模式进行优化。 特殊配对费用特别高,因为reg仍然需要穿透整段。

感谢使用<条码>代号在校服上填写。 (如果你知道配对的最长期限),仍然能够允许你在时间上使用reg子,以弥补投入的长度。

//update: 实际上,我刚刚认识到,这也适用于预先确定配对。 <<0>Java regex对O(1) 长度预设格式>。 也就是说,(?s)^[aeiou]{3}.*$“,如果在O(N)上用3个下级字母打字开始,那么最好到O(1)

我认为,预设配比会更方便,但我认为不可能形成一个<条码>O(1)-runtime patterns,以与上述匹配(除非有人能证明我错)。

很明显,你可以做以下工作:<条码>、代谢(0, 3)^[aeiou]{3}.*$”,但模式本身仍然是<条码>O(N);你使用<条码>代谢/条码>,仅人工减缩<条码>。

因此,对于真正长的胎体的任何类型的定级-宽度序/体配对,在使用reg之前,应先使用<条码>代号;否则,请在<条码>上填写

在我的测试中,我发现:

Using java s String.split method (which uses regex) took 2176ms under 1,000,000 iterations. Using this custom split method took 43ms under 1,000,000 iterations.

Of course, it will only work if your "regex" is completely literal, but in those cases, it will be much faster.

List<String> array = new ArrayList<String>();
String split = "ab";
String string = "aaabaaabaa";
int sp = 0;
for(int i = 0; i < string.length() - split.length(); i++){              
    if(string.substring(i, i + split.length()).equals(split)){
        //Split point found
        array.add(string.substring(sp, i));
        sp = i + split.length();
        i += split.length();
    }
}
if(sp != 0){
    array.add(string.substring(sp, string.length()));
}
return array;

因此,回答你的问题,从理论上说,这是否更快? 是的,绝对是,我的算法是O(n),其中N是脚架分离的长度。 (我不敢肯定会是什么。) 这实际上是否更快? 同样,我节省了100多万座挖土机,基本是两秒钟。 因此,这取决于你们的需要,但我担心的是,把所有使用reg制成非排他性版本的法典合并起来,事实上,如果模式非常复杂,可能有必要采用任何途径,这种方式就象这一轮功一样。 然而,如果你重新分割 com,这一方法会更好,尽管“更好”在这里是主观的。

情况和执行取决于模式和实施情况,但并非始终如此,有时是缓慢的。

一个快速的例子,比正常的更替缓慢2x,但我认为这并不缓慢。

>>> import time,re
>>>
>>> x="abbbcdexfbeczexczczkef111anncdehbzzdezf" * 500000
>>>
>>> start=time.time()
>>> y=x.replace("bc","TEST")
>>> print time.time()-start,"s"
0.350999832153 s
>>>
>>> start=time.time()
>>> y=re.sub("bc","TEST",x)
>>> print time.time()-start,"s"
0.751000165939 s
>>>




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签