2015-05-15 15 views
9

To moja sytuacja: Mam ciąg reprezentujący tekstSprawdź, czy ciąg zawiera listę podciągów i zapisać Dopasowany ones

string myText = "Text to analyze for words, bar, foo"; 

i lista słów do wyszukiwania w niej

List<string> words = new List<string> {"foo", "bar", "xyz"}; 

chciałbym poznać najbardziej skuteczną metodę, jeśli istnieje, aby otrzymać listę słów zawartych w tekście, coś takiego:

List<string> matches = myText.findWords(words) 
+0

efektywne pod względem czasu procesora lub pamięci? – adv12

+0

Jaki byłby rozmiar 'myText' i ile operacji wyszukiwania będziesz wykonywał/ – npinti

+0

Musisz zdefiniować, co masz na myśli przez" słowo ". Czy "foo" powinno być dopasowane w łańcuchu typu "This is foobar"? Odpowiedzi "Zawiera" pasowałyby do tego, natomiast odpowiedzi "Split" nie. – juharr

Odpowiedz

7

Nie ma specjalnej analizy w tym zapytaniu, z wyjątkiem, że musisz użyć metody Contains. Więc może spróbuj tego:

string myText = "Text to analyze for words, bar, foo"; 

List<string> words = new List<string> { "foo", "bar", "xyz" }; 

var result = words.Where(i => myText.Contains(i)).ToList(); 
//result: bar, foo 
+0

Jest to prawdopodobnie najlepsza opcja, uwzględniająca efektywność czasu kodowania (której nie należy lekceważyć). –

+0

@DrewKennedy o ile problem nie jest skomplikowany, dlaczego nie wybrać najbardziej prostego i kompaktowego rozwiązania? –

+0

@HosseinNarimaniRad Zgadzam się, że nie ma Nieważne. Myślę, że komentarz odnosi się do tej metody, wymagającej wielokrotnych podań przez ciąg, co nie jest konieczne. Ponadto istnieje algorytm Boyer-Moore-Horspool, który może znacznie przyspieszyć algorytm, jeśli słowa są stosunkowo długie. – Bas

5

Można użyć HashSet<string> i przecinają obie kolekcje:

string myText = "Text to analyze for words, bar, foo"; 
string[] splitWords = myText.Split(' ', ','); 

HashSet<string> hashWords = new HashSet<string>(splitWords, 
               StringComparer.OrdinalIgnoreCase); 
HashSet<string> words = new HashSet<string>(new[] { "foo", "bar" }, 
              StringComparer.OrdinalIgnoreCase); 

hashWords.IntersectWith(words); 
+1

Chociaż obsługuje to podany przykład, nie będzie działać z ciągiem takim jak "Tutaj jest foo! Gdzie jest pasek? Jestem xyz". Zasadniczo musisz podzielić na wszystko, co może oddzielić słowa. Również PO nie wspomniał, czy "foo" powinno być dopasowane w łańcuchu, jak "To jest foobar". – juharr

+0

@juharr To jest przykład tego, co OP może zrobić z 'HashSet'. Może podzielić się dowolnym separatorem, jakiego chce. Może również przyciąć struny przed włożeniem ich do kolekcji, czego nie zrobiłem. –

+0

Całkowicie się zgadzam, że to jest droga, którą należy przejść, jeśli OP chce spojrzeć na słowa, a nie tylko na pod-łańcuch. Po prostu pomyślałem, że należy podkreślić, że proces dzielenia może być bardziej skomplikowany. – juharr

0

Bawiąc się z ideą, że chcesz być w stanie wykorzystać myText.findWords(words), można dokonać przedłużenia metoda do klasy String, aby zrobić to, co chcesz.

public static class StringExtentions 
{ 
    public static List<string> findWords(this string str, List<string> words) 
    { 
     return words.Where(str.Contains).ToList(); 
    } 
} 

wykorzystania:

string myText = "Text to analyze for words, bar, foo"; 
List<string> words = new List<string> { "foo", "bar", "xyz" }; 
List<string> matches = myText.findWords(words); 
Console.WriteLine(String.Join(", ", matches.ToArray())); 
Console.ReadLine(); 

Wyniki:

foo bar Roztwór

2

regex

var words = new string[]{"Lucy", "play", "soccer"}; 
var text = "Lucy loves going to the field and play soccer with her friend"; 
var match = new Regex(String.Join("|",words)).Match(text); 
var result = new List<string>(); 

while (match.Success) { 
    result.Add(match.Value); 
    match = match.NextMatch(); 
} 

//Result ["Lucy", "play", "soccer"] 
+0

Powinieneś użyć Regex.Escape – mrwaim

0

Oto proste rozwiązanie, które odpowiada za spacji i interpunkcji:

static void Main(string[] args) 
{ 
    string sentence = "Text to analyze for words, bar, foo";    
    var words = Regex.Split(sentence, @"\W+"); 
    var searchWords = new List<string> { "foo", "bar", "xyz" }; 
    var foundWords = words.Intersect(searchWords); 

    foreach (var item in foundWords) 
    { 
     Console.WriteLine(item); 
    } 

    Console.ReadLine(); 
} 
Powiązane problemy