1337 Stimmen

\d weniger effizient als [0-9]

Ich habe gestern einen Kommentar zu einer Antwort gemacht, in der jemand [0123456789] in einem Regex verwendet hat, anstatt [0-9] oder \d. Ich habe gesagt, dass es wahrscheinlich effizienter ist, einen Bereich oder einen Ziffernspezifizierer zu verwenden als eine Zeichenmenge.

Heute habe ich beschlossen, das zu testen und zu meiner Überraschung herausgefunden, dass (zumindest im c# Regex-Engine) \d anscheinend weniger effizient ist als die anderen beiden, die sich nicht viel zu unterscheiden scheinen. Hier ist meine Testausgabe über 10000 zufällige Zeichenfolgen mit jeweils 1000 zufälligen Zeichen, von denen 5077 tatsächlich eine Ziffer enthalten:

Regex \d           dauerte 00:00:00.2141226 Ergebnis: 5077/10000
Regex [0-9]        dauerte 00:00:00.1357972 Ergebnis: 5077/10000  63.42 % des ersten
Regex [0123456789] dauerte 00:00:00.1388997 Ergebnis: 5077/10000  64.87 % des ersten

Das überrascht mich aus zwei Gründen, über die ich gerne mehr erfahren würde:

  1. Ich hätte gedacht, dass der Bereich viel effizienter implementiert wäre als die Menge.
  2. Ich verstehe nicht, warum \d schlechter ist als [0-9]. Gibt es mehr zu \d als nur eine Abkürzung für [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();
            //10K zufällige Zeichenfolgen
            for (var i = 0; i < 10000; i++)
            {
                //zufällige Zeichenfolge generieren
                var sb = new StringBuilder();
                for (var c = 0; c < 1000; c++)
                {
                    //zufällig a-z hinzufügen
                    sb.Append((char)('a' + rand.Next(26)));
                }
                //in ungefähr 50 % von ihnen, eine Ziffer einfügen
                if (rand.Next(2) == 0)
                {
                    //Ersetze 1 Zeichen durch eine Ziffer 0-9
                    sb[rand.Next(sb.Length)] = (char)('0' + rand.Next(10));
                }
                strings.Add(sb.ToString());
            }

            var basisZeit = testPerfomance(strings, @"\d");
            Console.WriteLine();
            var testZeit = testPerfomance(strings, "[0-9]");
            Console.WriteLine("  {0:P2} des ersten", testZeit.TotalMilliseconds / basisZeit.TotalMilliseconds);
            testZeit = testPerfomance(strings, "[0123456789]");
            Console.WriteLine("  {0:P2} des ersten", testZeit.TotalMilliseconds / basisZeit.TotalMilliseconds);
        }

        private static TimeSpan testPerfomance(List strings, string regex)
        {
            var sw = new Stopwatch();

            int erfolge = 0;

            var rex = new Regex(regex);

            sw.Start();
            foreach (var str in strings)
            {
                if (rex.Match(str).Success)
                {
                    erfolge++;
                }
            }
            sw.Stop();

            Console.Write("Regex {0,-12} dauerte {1} Ergebnis: {2}/{3}", regex, sw.Elapsed, erfolge, strings.Count);

            return sw.Elapsed;
        }
    }
}

1655voto

Sina Iravanian Punkte 15531

\d überprüft alle Unicode-Ziffern, während [0-9] auf diese 10 Zeichen beschränkt ist. Beispielsweise sind persische Ziffern, , ein Beispiel für Unicode-Ziffern, die mit \d, aber nicht mit [0-9] übereinstimmen.

Sie können eine Liste aller solcher Zeichen mit folgendem Code generieren:

var sb = new StringBuilder();
for(UInt16 i = 0; i < UInt16.MaxValue; i++)
{
    string str = Convert.ToChar(i).ToString();
    if (Regex.IsMatch(str, @"\d"))
        sb.Append(str);
}
Console.WriteLine(sb.ToString());

Das erzeugt:

0123456789

283voto

weston Punkte 52445

Dank an ByteBlast, der dies in den Dokumenten bemerkt hat. Einfach den Regex-Konstruktor ändern:

var rex = new Regex(regex, RegexOptions.ECMAScript);

Gibt neue Messwerte:

Regex \d           dauerte 00:00:00,1355787 Ergebnis: 5077/10000
Regex [0-9]        dauerte 00:00:00,1360403 Ergebnis: 5077/10000  100,34 % des ersten
Regex [0123456789] dauerte 00:00:00,1362112 Ergebnis: 5077/10000  100,47 % des ersten

124voto

İsmet Alkan Punkte 5221

Von Bedeutet „\d“ in regex eine Ziffer?:

[0-9] ist nicht dasselbe wie \d. [0-9] passt nur zu den Zeichen 0123456789, während \d zu [0-9] und anderen Ziffern passt, zum Beispiel Ost-Arabische Ziffern

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X