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;
}
}
}
c#
regex
performance
Weston
quelle
quelle
\d
befasst sich mit Gebietsschemas. ZB verwendet Hebräisch Buchstaben für Ziffern.\d
sie in verschiedenen Sprachen nicht dasselbe bedeutet. In Java zum Beispiel\d
stimmt tatsächlich nur 0-9 übereinAntworten:
\d
Überprüft alle Unicode-Ziffern,[0-9]
ist jedoch auf diese 10 Zeichen beschränkt. Beispielsweise sind persische Ziffern۱۲۳۴۵۶۷۸۹
ein Beispiel für Unicode-Ziffern, die mit übereinstimmen\d
, aber nicht[0-9]
.Mit dem folgenden Code können Sie eine Liste aller dieser Zeichen erstellen:
Was erzeugt:
quelle
Dank an ByteBlast, dass Sie dies in den Dokumenten bemerkt haben. Ändern Sie einfach den Regex-Konstruktor:
Gibt neue Zeiten:
quelle
RegexOptions.ECMAScript
?ECMAScript
(\u1234
) weiterhin gültig . Es sind "nur" die Kurzzeichen-Zeichenklassen, die ihre Bedeutung ändern (wie\d
), und die Unicode-Eigenschafts- / Skript-Kurzzeichen, die verschwinden (wie\p{N}
).Von Bedeutet "\ d" in Regex eine Ziffer? ::
quelle
If ECMAScript-compliant behavior is specified, \d is equivalent to [0-9].
var rex = new Regex(regex, RegexOptions.ECMAScript);
macht sie alle in Bezug auf die Leistung so gut wie nicht zu unterscheiden.Als Ergänzung zur Top-Antwort von Sina Iravianian finden Sie hier eine .NET 4.5-Version (da nur diese Version die UTF16-Ausgabe (siehe die ersten drei Zeilen) unterstützt) seines Codes unter Verwendung des gesamten Bereichs der Unicode-Codepunkte. Aufgrund des Mangels an angemessener Unterstützung für höhere Unicode-Flugzeuge ist es vielen Menschen nicht bewusst, immer nach den oberen Unicode-Flugzeugen zu suchen und diese einzuschließen. Trotzdem enthalten sie manchmal einige wichtige Zeichen.
Aktualisieren
Da
\d
Nicht-BMP-Zeichen in Regex nicht unterstützt werden (danke xanatos ), hier eine Version, die die Unicode-Zeichendatenbank verwendetDie folgende Ausgabe ergibt:
quelle
Regex
keine Nicht-BMP-Zeichen unterstützt. Am Ende ist es also nutzlos, mit einem regulären Ausdruck nach Zeichen> 0xffff zu suchen.\ d überprüft alle Unicodes, während [0-9] auf diese 10 Zeichen beschränkt ist. Wenn nur 10 Ziffern, sollten Sie verwenden. Andere empfehle ich die Verwendung von \ d , Weil weniger geschrieben wird.
quelle