2013-05-08 4 views
3

Проблемы проста ...
Дано:Поиск списка фраз против словесного списка и подсчитать количество появлений

-> список нечестных слов, скажу List1.
-> список строк (или фраз) для поиска этих мерзких слов-, скажем list2

Желаемый результат: граф фраз, которые соответствовали по меньшей мере, один из нечистых-слов.

Пример:
List1: "кошка", "собака", "мышь", "Ницца животное"
List2: "Кошка хорошо". «Плохая собака», «Хорошая кошка и собака», «Хорошее животное», «Привет», «Привет, мышь», «Это плохо»

Вывод: 5 фраз содержат по крайней мере 1 грязное слово.

Что я сделал:.

int sum = list1.Sum(s => list2.Count(t => t.Contains(s))); 

Это занимает около 38 секунд для списка фола слов 5600 фраз, а также около 4000 строк для поиска в (четырехъядерный, 4 Гб оперативной памяти) .. WAYYYYYY TOO SLOW!

Я искал решения или алгоритмы, которые могут существовать для этого ... Не удалось найти.

Даже если кто-то может указать мне в правильном направлении, назвав алго, показывая фрагмент кода или просто указав палец (!!), было бы здорово!

+0

Я понятия не имею, если это действительно поможет, но вы могли бы попытаться составить регулярное выражение из всех мерзких слов (один регулярное выражение, содержащее их все, и скомпилируйте его), чем запустить его против фраз. Я просто догадываюсь, что скомпилированное регулярное выражение быстрее, чем ваш запрос linq. – Alxandr

+0

[Инвертированный индекс] (http://en.wikipedia.org/wiki/Inverted_index) или [Индексирование поисковых систем] (http://en.wikipedia.org/wiki/Search_engine_indexing) – I4V

+0

Возможно, использование регулярных выражений будет более эффективным , – filipko

ответ

3

Это должно быть более эффективным, поскольку Any перерывов как можно скорее:

int contains = phrases.Count(p => foulWords.Any(fw => p.Contains(fw))); 

Ваш подход также не является оптимальным, так как отправной точкой является List1 (foulWords), так что вам нужно сумму каждого подсчета, который является неэффективным , Правильный результат должен быть между 0 (без соответствия фол-слову) и phrases.Count (все фразы содержат ложное слово). Поэтому отправной точкой должно быть phrases.

Demo

Q: Не могли бы вы помочь мне изменить код выше, чтобы также дать мне INDEX фразы в списке?

Да:

var wordIndexes = phrases.Select((phrase, index) => new { phrase, index }) 
    .Where(x => foulWords.Any(fw => x.phrase.Contains(fw))); 

foreach (var wordIndex in wordIndexes) 
    Console.WriteLine("Word: {0} Index: {1}", wordIndex.phrase, wordIndex.index); 

Результат:

Word: A cat is good  Index: 0 
Word: a dog is bad   Index: 1 
Word: cat and dog are good Index: 2 
Word: Nice animal   Index: 3 
Word: Hello mouse   Index: 5 
+0

+1 - собирался опубликовать примерно то же самое: var count = phrases.Count (p => foul.Any (tf => p.Contains (tf))); – Nathan

+0

Это отлично работает для меня ... Спасибо! :) –

+0

@Tim - Могли бы вы также помочь мне изменить приведенный выше код, чтобы также дать мне INDEX фразы в списке? Таким образом, выход будет: 5 (0,1,2,5, ....) Я просто изменил COUNT на WHERE и выбрал ... Это снова медленно ... Что я мог делать неправильно ?! ! –

Смежные вопросы