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;
}
}
}
c#
regex
performance
Weston
fonte
fonte
\d
lide com locais. Por exemplo, o hebraico usa letras para dígitos.\d
não significa a mesma coisa em diferentes idiomas. Em Java, por exemplo\d
, de fato corresponde apenas de 0 a 9 #Respostas:
\d
verifica todos os dígitos Unicode, enquanto[0-9]
está limitado a esses 10 caracteres. Por exemplo, dígitos persas ,,۱۲۳۴۵۶۷۸۹
são um exemplo de dígitos Unicode correspondentes\d
, mas não correspondentes[0-9]
.Você pode gerar uma lista de todos esses caracteres usando o seguinte código:
O que gera:
fonte
Os nossos agradecimentos à ByteBlast por ter observado isso nos documentos. Apenas alterando o construtor regex:
Dá novos horários:
fonte
RegexOptions.ECMAScript
faz?ECMAScript
(\u1234
). São "apenas" as classes de caracteres abreviados que mudam de significado (como\d
) e as propriedades / scripts Unicode que desaparecem (como\p{N}
).De "\ d" em regex significa um dígito? :
fonte
If ECMAScript-compliant behavior is specified, \d is equivalent to [0-9].
var rex = new Regex(regex, RegexOptions.ECMAScript);
torna todos praticamente indistinguíveis em termos de desempenho.Além da resposta principal do Sina Iravianian , aqui está uma versão do .NET 4.5 (já que apenas essa versão suporta saída UTF16, nas três primeiras linhas) de seu código, usando toda a gama de pontos de código Unicode. Devido à falta de suporte adequado para planos Unicode mais altos, muitas pessoas não estão cientes de sempre procurar e incluir os planos Unicode superiores. No entanto, eles às vezes contêm alguns caracteres importantes.
Atualizar
Como
\d
não suporta caracteres não BMP no regex (obrigado xanatos ), aqui uma versão que usa o banco de dados de caracteres UnicodeRendendo a seguinte saída:
fonte
Regex
não suporta caracteres não BMP. Portanto, no final, verificar caracteres> 0xffff com um regex é inútil.\ d verifica todos os Unicode, enquanto [0-9] está limitado a esses 10 caracteres. Se apenas 10 dígitos, você deve usar. Outros eu recomendo usar \ d , porque escrever menos.
fonte