Скажем, у меня есть ряд ключевых слов в массиве {"Олимпийские игры", "спортивный теннис лучше всего", "теннис", "теннис управляет"}
У меня затем есть большой список (до 50 за один раз) строк (или на самом деле пишет в Твиттере), таким образом, они - макс. из 140 символов.
Я хочу посмотреть на каждую строку и видеть, какие ключевые слова присутствуют там. В случае, где ключевое слово состоит из нескольких слов как "спортивный теннис лучше всего", слова не должны быть вместе в строке, но все они должны обнаружиться.
Я испытываю затруднения наличия при выяснении алгоритма, который делает это эффективно.
Вы у парней есть предложения на способе сделать это?Спасибо!
Править: Объяснить немного лучше каждое ключевое слово связали идентификатор с ним, таким образом {1: "Олимпийские игры", 2: "спортивный теннис лучше всего", 3: "теннис", 4: "теннис управляет"}
Я хочу пройти список строк/твитов и видеть, которому соответствует группа ключевых слов. Вывод должен быть, этот твит тяготеет к ключевому слову № 4. (несколько соответствий могут быть сделаны, таким образом, что-либо, что соответствует ключевому слову 2, также соответствовало бы 3 - так как они оба содержат теннис).
Когда существует несколько слов в ключевом слове, например, "спортивный теннис лучше всего", они не должны появляться вместе, но иметь ко всем, появляются. например, это будет правильно соответствовать: "я просто играл в теннис, я люблю спорт, это является лучшим"..., так как эта строка содержит "спортивный теннис лучше всего", это будет соответствовать и будет связано с keywordID (который является 2 для этого примера).
Редактирование 2: Нечувствительный к регистру.
IEnumerable<string> tweets, keywords;
var x = tweets.Select(t => new
{
Tweet = t,
Keywords = keywords.Where(k => k.Split(' ')
.All(t.Contains))
.ToArray()
});
Я бы посоветовал поместить все ваши ключевые слова в список строк, а затем просмотреть ваш список данных (твитов и т. Д.) В виде другого списка строк.
Сделайте что-то вроде этого:
Dim matchingStrings As Dictonary(String, String);
For Each stringToSearch As String In tweetList
For Each keyword As String In keywordList
If stringToSearch.Contains(keyword)
matchingString.Add(stringToSearch, keyword);
break; End IF End For End For
Then MatchingString Содержит все ваши совпадения
EDIT: In C # И для нескольких слов в списке ключевых слов
Dictionary<string, string> matchingString = New Dictionary<string, string>;
foreach (String stringToSearch In tweetList){
foreach (String keyword In keywordList){
If(stringToSearch.Contains(keyword){
matchingString.Add(stringToSearch, keyword);
break;
}
else if{
List<string> split = keyword.Split(" ")
foreach(String sKeyword In split){
If(stringToSearch.Contains(keyword){
matchingString.Add(stringToSearch, keyword);
break;
}
}
}
} }
Множественные шаблоны можно очень эффективно искать с помощью нескольких алгоритмов, таких как алгоритм из Aho-Corasick (с использованием дерева) или алгоритм из Wu и Manber .
Если производительность критична, я предлагаю взять любой из них. Для поиска в нескольких строках может быть наиболее эффективным объединить все ваши 50 строк в одну большую строку, сохраняя начальные позиции отдельных строк.
Может быть, что-то вроде этого?
string[] keywords = new string[] {"olympics", "sports tennis best", "tennis", "tennis rules"};
string testString = "I like sports and the olympics and think tennis is best.";
string[] usedKeywords = keywords.Where(keyword => keyword.Split(' ').All(s => testString.Contains(s))).ToArray();
Есть способы предварительной обработки строк, чтобы сделать поиск более эффективным, но я думаю, что накладные расходы больше, чем выгода для таких коротких строк . Это не так много данных, поэтому я бы просто перебрал строки:
foreach (string tweet in tweets) {
foreach (string keywords in theArray) {[
string[] keyword = keywords.Split(' ');
bool found = true;
foreach (string word in keyword) {
if (tweet.indexOf(word) == -1) {
found = false;
break;
}
}
if (found) {
// all words exist in the tweet
}
}
}
Упс.
foreach (var s in strings)
{
foreach (var keywordList in keywordSet)
{
if (s.ContainsAll(keywordList))
{
// hit!
}
}
}
...
private bool ContainsAll(this string s, string keywordList)
{
foreach (var singleWord in keywordList.Split(' '))
{
if (!s.Contains(singleWord)) return false;
}
return true;
}