\d est moins efficace que [0-9]

j'ai fait un commentaire hier sur une réponse où quelqu'un avait utilisé [0123456789] dans une expression régulière plutôt que [0-9] ou \d . J'ai dit que c'était probablement plus efficace d'utiliser une fourchette ou un chiffre spécificateur qu'un jeu de caractères.

j'ai décidé de tester cela aujourd'hui et j'ai découvert à ma surprise que (dans le moteur c# regex au moins) \d semble être moins efficace que l'un des deux autres qui ne semblent différer beaucoup. Voici ma sortie de test sur 10000 chaînes aléatoires de 1000 caractères aléatoires avec 5077 contenant en fait un chiffre:

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

C'est une surprise pour moi pour deux raisons:

  1. j'aurais pensé que la gamme serait mise en œuvre beaucoup plus efficacement que l'ensemble.
  2. Je ne comprends pas pourquoi \d est pire que [0-9] . Y a-t-il plus à \d que de simples raccourcis pour [0-9] ?

voici le code d'essai:

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;
        }
    }
}
1137
demandé sur Peter Mortensen 2013-05-18 11:18:40
la source

6 ответов

Autres questions sur c# performance regex