Prevenir partidas duplicados em RegEx
Pergunta
O código a seguir
string expression = "(\\{[0-9]+\\})";
RegexOptions options = ((RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline) | RegexOptions.IgnoreCase);
Regex tokenParser = new Regex(expression, options);
MatchCollection matches = tokenParser.Matches("The {0} is a {1} and the {2} is also a {1}");
irá corresponder e captura de "{0}", "{1}", "{2}" e "{1}".
É possível alterá-lo (ou a expressão regular ou a opção do RegEx) para que ele iria corresponder e captura de "{0}", "{1}" e "{2}". Em outras palavras, cada jogo só deve ser capturado uma vez?
Solução
Aqui está algo que você poderia usar para uma solução regex puro:
Regex r = new Regex(@"(\{[0-9]+\}|\[[^\[\]]+\])(?<!\1.*\1)",
RegexOptions.Singleline);
Mas por uma questão de eficiência e facilidade de manutenção, você é provavelmente melhor fora com uma solução mista como o que você postou.
Outras dicas
Aqui está o que eu vim acima com.
private static bool TokensMatch(string t1, string t2)
{
return TokenString(t1) == TokenString(t2);
}
private static string TokenString(string input)
{
Regex tokenParser = new Regex(@"(\{[0-9]+\})|(\[.*?\])");
string[] tokens = tokenParser.Matches(input).Cast<Match>()
.Select(m => m.Value).Distinct().OrderBy(s => s).ToArray<string>();
return String.Join(String.Empty, tokens);
}
Note que a diferença na expressão regular daquele em minha pergunta é devido ao fato de que eu atender a dois tipos de ficha; que foram contados delimitados por {} e aqueles nomeados delimitados por [];
As expressões regulares resolver muitos problemas, mas não todos os problemas. Que tal usar outras ferramentas na caixa de ferramentas?
var parameters = new HashSet<string>(
matches.Select(mm => mm.Value).Skip(1));
ou
var parameters = matches.Select(mm => mm.Value).Skip(1).Distinct();
Se você só quer um exemplo alterações
string expression = "(\\{[0-9]+\\})"; \\one or more repetitions
para
string expression = "(\\{[0-9]{1}})"; \\Exactly 1 repetition