匹配C#中字典的正则表达式

时间:2009-09-10 22:26:17

标签: c# regex dictionary match

我正在尝试使用某种数据对象(我在想字典)来保存正则表达式的TON作为键,然后我需要获取一串文本,然后匹配它们以获得实际值来自字典。我需要一种有效的方法来处理大量数据。

我在C#,我不知道从哪里开始。

6 个答案:

答案 0 :(得分:8)

为什么不使用LINQ?

Dictionary<string, string> myCollection = new Dictionary<string, string>();

myCollection.Add("(.*)orange(.*)", "Oranges are a fruit.");
myCollection.Add("(.*)apple(.*)", "Apples have pips.");
myCollection.Add("(.*)dog(.*)", "Dogs are mammals.");
// ...

string input = "tell me about apples and oranges";

var results = from result in myCollection
              where Regex.Match(input, result.Key, RegexOptions.Singleline).Success
              select result;

foreach (var result in results)
{
    Console.WriteLine(result.Value);
}

// OUTPUT:
//
// Oranges are a fruit.
// Apples have pips.

答案 1 :(得分:0)

我不确定你是否真的需要正则表达式 - 你可以使用trie。代表字典是trie的常见应用。 (我假设你的意思是字词列表中的字典,而不是“关联数组”的意思)。

答案 2 :(得分:0)

你的意思是匹配正则表达式的字符串以获得正则表达式匹配?或者只是文字匹配?换句话说,你要成为其中一个正则表达式的字符串,还是要将正则表达式应用到的一些数据?

如果它是一个正则表达式并且你想在列表中找到它,你不需要一个字典,那些是2部分容器。您可以使用List或StringCollection,并询问IndexOf(mytString),-1表示它不在那里。

答案 3 :(得分:0)

如果您的正则表达式不是简单的单字符串,并且您关心效率,那么您需要在单个NFA (nondeterministic finite-state automaton中表示它们,其值为最终状态。如果输入可能匹配多个正则表达式,那么最终状态将需要一组值。

此时,您已准备好考虑优化自动机。如果它可以实际确定(这给你一个可以指数大于NFA的DFA),那么一定要做到这一点。一旦你有了DFA,你就可以有效地(并且唯一地达到同构)最小化它(但是因为你在最终状态中有值,所以需要对usual algorithm进行明显的修改。)

还有一些技术可以直接减少NFA。例如,如果两个状态具有相同的后缀集({(其余字符串,值)}),则它们是等效的并且可以组合。非循环NFA中的等价可以从最终状态开始通过hash-consing完成。

答案 4 :(得分:0)

请记住,如果您计划多次使用正则表达式,则可以在编译时创建正则表达式对象并重新使用它以减少开销。

Regex RegexObject = new Regex(Pattern, RegexOptions.Compiled);

使用此模型最好存储正则表达式对象而不是模式字符串。

答案 5 :(得分:0)

以下回购中有一个RegexPatternDictionaryImpl类型,可用于将正则表达式存储为键,并将所需的任何值存储为值。不过,该词典并未针对性能进行优化。它只是对键进行线性扫描,并将它们与给定的字符串匹配,以返回所有匹配的值。但是,对于较小的用例,此字典就足够了:

https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtras/Dictionary/RegexPatternDictionaryImpl.cs

字典相对稳定,在此处编写了许多测试:

https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtrasTest/Dictionary/RegexPatternDictionaryTest.cs

如果您想自己编写代码,以下是编写此答案时的源代码快照。注意:您可能必须解开库的某些方面才能使用此功能:

namespace CsharpExtras.Dictionary
{
    public class RegexPatternDictionaryImpl<TValue> : 
      IRegexPatternDictionary<TValue>
    {
    private readonly IDictionary<string, TValue> _baseDictionary;
    private readonly IDictionary<Regex, string> _regexDictionary;

    public RegexPatternDictionaryImpl()
    {
        _baseDictionary = new Dictionary<string, TValue>();
        _regexDictionary = new Dictionary<Regex, string>();
    }

    public void Add(string pattern, TValue value)
    {
        AddRegexToDictionary(pattern, pattern, value);
    }

    public ICollection<TValue> FindAllValuesThatMatch(string textKey)
    {
        ICollection<TValue> result = new List<TValue>();
        foreach (var item in _regexDictionary.Where(r => r.Key.IsMatch(textKey)))
        {
            result.Add(_baseDictionary[item.Value.ToString()]);
        }
        return result;
    }

    public bool HasMatch(string textKey)
    {
        return _regexDictionary.Any(r => r.Key.IsMatch(textKey));
    }

    public ICollection<(string pattern, TValue values)> FindAllPatternValuePairsThatMatch(string textKey)
    {
        ICollection<(string pattern, TValue values)> result = new List<(string pattern, TValue values)>();
        foreach (KeyValuePair<Regex, string> item in _regexDictionary.Where(r => r.Key.IsMatch(textKey)))
        {
            result.Add((item.Key.ToString(), _baseDictionary[item.Value.ToString()]));
        }
        return result;
    }

    public void AddEscapedFullMatchPattern(string pattern, TValue value)
    {
        string escapedPattern = Regex.Escape(pattern);
        string fullMatchPattern = MakePatternMatchFullString(escapedPattern);
        AddRegexToDictionary(fullMatchPattern, pattern, value);
    }

    public void AddFullMatchPattern(string pattern, TValue value)
    {
        string fullMatchPattern = MakePatternMatchFullString(pattern);
        AddRegexToDictionary(fullMatchPattern, pattern, value);
    }

    #region Base dictionary methods
    public TValue this[string key] { get => _baseDictionary[key]; set => _baseDictionary[key] = value; }

    public ICollection<string> Keys => _baseDictionary.Keys;

    public ICollection<TValue> Values => _baseDictionary.Values;

    public int Count => _baseDictionary.Count;

    public bool IsReadOnly => _baseDictionary.IsReadOnly;

    public void Add(KeyValuePair<string, TValue> item)
    {
        _baseDictionary.Add(item);
    }

    public void Clear()
    {
        _baseDictionary.Clear();
    }

    public bool Contains(KeyValuePair<string, TValue> item)
    {
        return _baseDictionary.Contains(item);
    }

    public bool ContainsKey(string key)
    {
        return _baseDictionary.ContainsKey(key);
    }

    public void CopyTo(KeyValuePair<string, TValue>[] array, int arrayIndex)
    {
        _baseDictionary.CopyTo(array, arrayIndex);
    }

    public IEnumerator<KeyValuePair<string, TValue>> GetEnumerator()
    {
        return _baseDictionary.GetEnumerator();
    }

    public bool Remove(string key)
    {
        return _baseDictionary.Remove(key);
    }

    public bool Remove(KeyValuePair<string, TValue> item)
    {
        return _baseDictionary.Remove(item);
    }

    public bool TryGetValue(string key, out TValue value)
    {
        return _baseDictionary.TryGetValue(key, out value);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _baseDictionary.GetEnumerator();
    }
    #endregion

    private void AddRegexToDictionary(string actualPattern, string keyPattern, TValue value)
    {
        Regex regex = new Regex(actualPattern, RegexOptions.Compiled);
        _baseDictionary.Add(keyPattern, value);
        _regexDictionary.Add(regex, keyPattern);
    }

    private string MakePatternMatchFullString(string pattern)
    {
        string updatedPattern = pattern;
        if (!pattern.StartsWith("^"))
        {
            updatedPattern = "^" + updatedPattern;
        }
        if (!pattern.EndsWith("$"))
        {
            updatedPattern += "$";
        }
        return updatedPattern;
    }
}

}

披露

上述存储库由我在我的个人GitHub网站上维护。