Ich habe gestern einen Kommentar zu einer Antwort abgegeben, bei der jemand [0123456789]
einen regulären Ausdruck anstelle von [0-9]
oder verwendet hat \d
. Ich sagte, es sei wahrscheinlich effizienter, einen Bereichs- oder Ziffernbezeichner als einen Zeichensatz zu verwenden.
Ich habe mich heute entschlossen, das zu testen, und zu meiner Überraschung herausgefunden, dass (zumindest in der C # -Regex-Engine) \d
weniger effizient zu sein scheint als die beiden anderen, die sich nicht sehr zu unterscheiden scheinen. Hier ist meine Testausgabe über 10000 zufällige Zeichenfolgen mit 1000 zufälligen Zeichen, wobei 5077 tatsächlich eine Ziffer enthält:
Regular expression \d took 00:00:00.2141226 result: 5077/10000
Regular expression [0-9] took 00:00:00.1357972 result: 5077/10000 63.42 % of first
Regular expression [0123456789] took 00:00:00.1388997 result: 5077/10000 64.87 % of first
Es ist eine Überraschung für mich aus zwei Gründen:
- Ich hätte gedacht, dass der Bereich viel effizienter implementiert werden würde als das Set.
- Ich kann nicht verstehen, warum
\d
es schlimmer ist als[0-9]
. Gibt es mehr\d
als nur eine Abkürzung[0-9]
?
Hier ist der Testcode:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace SO_RegexPerformance
{
class Program
{
static void Main(string[] args)
{
var rand = new Random(1234);
var strings = new List<string>();
//10K random strings
for (var i = 0; i < 10000; i++)
{
//Generate random string
var sb = new StringBuilder();
for (var c = 0; c < 1000; c++)
{
//Add a-z randomly
sb.Append((char)('a' + rand.Next(26)));
}
//In roughly 50% of them, put a digit
if (rand.Next(2) == 0)
{
//Replace one character with a digit, 0-9
sb[rand.Next(sb.Length)] = (char)('0' + rand.Next(10));
}
strings.Add(sb.ToString());
}
var baseTime = testPerfomance(strings, @"\d");
Console.WriteLine();
var testTime = testPerfomance(strings, "[0-9]");
Console.WriteLine(" {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
testTime = testPerfomance(strings, "[0123456789]");
Console.WriteLine(" {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
}
private static TimeSpan testPerfomance(List<string> strings, string regex)
{
var sw = new Stopwatch();
int successes = 0;
var rex = new Regex(regex);
sw.Start();
foreach (var str in strings)
{
if (rex.Match(str).Success)
{
successes++;
}
}
sw.Stop();
Console.Write("Regex {0,-12} took {1} result: {2}/{3}", regex, sw.Elapsed, successes, strings.Count);
return sw.Elapsed;
}
}
}
\d
sie in verschiedenen Sprachen nicht dasselbe bedeutet. In Java zum Beispiel \d
stimmt tatsächlich nur 0-9 überein
\d
befasst sich mit Gebietsschemas. ZB verwendet Hebräisch Buchstaben für Ziffern.