2009-09-10 15 views
5

Próbuję mieć jakiś obiekt danych (myślę, że słownik), aby pomieścić TON wyrażeń regularnych jako klucze, a następnie muszę wziąć ciąg tekstu, a dopasuj się do nich, aby uzyskać rzeczywistą wartość ze Słownika. Potrzebuję skutecznego sposobu na zrobienie tego dla dużego zestawu danych.Dopasuj wyrażenie regularne ze słownika w C#

Jestem w C# i nie jestem pewien, od czego zacząć.

+0

Na podstawie dotychczasowych odpowiedzi warto podać więcej szczegółów w pytaniu dotyczącym konkretnej aplikacji. –

+1

Mniej więcej ile wyrażeń jest w tonie? Jak duży jest tekst, który będą pasować? Jak często będzie dostarczany nowy tekst? Jak szybko należy zwrócić wyniki? – TrueWill

Odpowiedz

7

Dlaczego nie używać 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. 
+0

Mam zamiar zacząć od tego rozwiązania, do tej pory działa dość szybko ze słownikiem około 500 pozycji. Jeśli będzie gorzej, przyjrzę się innym alternatywom. Dzięki! –

0

Nie jestem pewien, czy rzeczywiście potrzebujesz do tego wyrażeń regularnych - możesz użyć numeru trie. Reprezentowanie słowników jest powszechną aplikacją dla konesera. (Zakładam, że masz na myśli słownik jak na liście słów, a nie znaczenie "tablicy asocjacyjnej").

0

Czy chodzi o dopasowanie ciągu do wyrażeń regularnych, aby uzyskać dopasowanie do wyrażenia regularnego? Czy tylko dopasowanie tekstu? Innymi słowy, czy ciąg ma być jednym z tych wyrażeń regularnych, czy też niektórymi danymi, do których można zastosować wyrażenie regularne?

Jeśli jest to wyrażenie regularne i chcesz je znaleźć na liście, nie potrzebujesz słownika, są to 2-częściowe pojemniki. Możesz po prostu użyć List lub StringCollection i poprosić o IndexOf (mytString), -1 oznacza, że ​​go tam nie ma.

0

Jeśli wyrażenia regularne nie są trywialne single-strings, a zależy Ci na wydajności, którą chcesz do reprezentowania ich w jednym NFA (nondeterministic finite-state automaton, o wartościach w stanach końcowych. Jeśli dane wejściowe mogą pasować do więcej niż jednego wyrażenia regularnego, wówczas stany końcowe będą wymagały zestawu wartości.

W tym momencie jesteś gotowy rozważyć optymalizację automatu. Jeśli można go praktycznie zdeterminować (daje to DFA, który może być wykładniczo większy niż NFA), to zrób to. Kiedy już masz DFA, możesz efektywnie (i unikalnie do izomorfizmu) zminimalizować (ale ponieważ masz wartości w swoich końcowych stanach, konieczna jest oczywista modyfikacja usual algorithm).

Istnieją również techniki minimalizacji bezpośredniego NFA. Na przykład, jeśli dwa stany mają takie same zestawy sufiksów ({(reszta łańcucha, wartość)}) są one równoważne i mogą być łączone. Równoważność w acyklicznym NFA można uzyskać przez stany końcowe, zaczynając od hash-consing.

0

Pamiętaj, że jeśli zamierzasz używać wyrażeń regularnych więcej niż jeden raz, możesz utworzyć obiekt regex jako skompilowany i ponownie wykorzystać go w celu zmniejszenia narzutu.

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

Korzystając z tego modelu, najlepiej przechowywać obiekt regex niż ciąg wzoru.