Ontem fiz um comentário sobre uma resposta em que alguém usava [0123456789]
uma expressão regular em vez de [0-9]
ou \d
. Eu disse que provavelmente era mais eficiente usar um especificador de intervalo ou dígito do que um conjunto de caracteres.
Decidi testar isso hoje e descobri, para minha surpresa, que (pelo menos no mecanismo de regex C #) \d
parece ser menos eficiente do que qualquer um dos outros dois que não parecem diferir muito. Aqui está minha saída de teste com mais de 10000 seqüências aleatórias de 1000 caracteres aleatórios, com 5077 na verdade contendo um dígito:
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
É uma surpresa para mim por dois motivos:
- Eu teria pensado que o intervalo seria implementado com muito mais eficiência do que o conjunto.
- Não consigo entender por que
\d
é pior que[0-9]
. Existe mais do\d
que simplesmente abreviação para[0-9]
?
Aqui está o código do teste:
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
não significa a mesma coisa em diferentes idiomas. Em Java, por exemplo \d
, de fato corresponde apenas de 0 a 9 #
\d
lide com locais. Por exemplo, o hebraico usa letras para dígitos.