【问题标题】:Efficient way to search for phrases that contain specific words搜索包含特定单词的短语的有效方法
【发布时间】:2016-03-06 10:53:44
【问题描述】:

我需要最有效的 C# 方法。

假设:

  1. 集合1:{"I am good", He is best", They are poor", "Mostly they are average", "All are very nice"}
  2. 集合2:{"good", "best" ,"nice"}

我想搜索Collection1中的所有Collection2项目并将匹配结果存储在Collection3中,所以Collection3会是这样的:

集合3:{"I am good", "I am best", "All are very nice"}

【问题讨论】:

  • 看起来你需要一个倒排索引,看看 Lucene.NET 是怎么做的,或者直接使用那个库。
  • 我想知道您是否对该主题进行过任何研究。例如,在右侧的相关列中有What .NET collection provides the fastest search?
  • @EugenePodskal; Collection1 项目将像一个短语。 Collection2 项目将是一个单词,将在 Collection1 短语中搜索,然后将匹配的短语放入 Collection3。
  • @LucasTrzesniewski;你能用c#代码写例子吗?

标签: c# string search collections


【解决方案1】:

最好的方法。

string[] Collection1 = {"I am good", "He is best", "They are poor", "Mostly they are average", "All are very nice"};
string[] Collection2 = { "good", "best", "nice" };

var Collection3 = Collection1.Select(x => x.ToLower())
                   .Where(x => Collection2.Any(y => x.Contains(y))).ToArray();

【讨论】:

  • 未在 C# 2010 中编译。请您编写正确的代码。这看起来既简单又好。
  • 很好,很高兴为您提供帮助。
  • @p0iz0neR 我想指出,这个解决方案是O(lengthOfCollection2*lengthOfCollection1*averageLengthOfStringInCollection1),而带有查找的解决方案摊销O(lengthOfCollection1*averageAmountOfWordsInPhrase) 用于查找创建,摊销O(lengthOfCollection2) 用于任何后续 Collection2 已使用。因此,如果您需要性能,并且,特别是如果您需要使用多个不同的Collection2 进行此类搜索,那么这个解决方案是一个低效的解决方案,虽然非常简洁不仅可以处理单词,还可以处理子字符串/短语。
  • @EugenePodskal;好吧,我有一个不超过一千个的列表,并且它起作用了。我知道这不是最快的,并且会降低非常大的列表的性能。虽然对我来说没问题。
【解决方案2】:
IList<String> Collection3;

for(int i = 0 ; i < Collectio2.Count ; i++)
{
   foreach(String str in Collection1)
   {
      if(str.Contains(Collection2[i]))
      {
         Collection3.Add(str);
      }
   }
}

【讨论】:

  • 使用嵌套循环。我想避免递归循环。
  • 这种情况下需要使用LINQ
  • 我使用了 Dictionary 但它只返回 TRUE 或 FALSE 而不是 ContainsValue 函数的索引。
【解决方案3】:

假设您的 Collection2 项目是该词通常含义的词 [没有双关语],您可以使用 LINQ ToLookup - 这将为您提供适当的 MultiValueDictionary 类似物,并且您可以尝试类似:

var phrases = new[] { "I am good", "He is best", "They are poor", "Mostly they are average", "All are very nice", "Not so\tgood \t", };

var lookup = phrases
    .Select((phrase, index) =>
        new
        {
            phrase,
            index,
            words = phrase.Split((Char[])null, StringSplitOptions.RemoveEmptyEntries)
        })
    .SelectMany(item =>
        item
            .words
            .Select(word =>
                new
                {
                    word,
                    item.index,
                    item.phrase
                }))
    .ToLookup(
        keySelector: item => item.word,
        elementSelector: item => new { item.phrase, item.index });

var wordsToSearch = new[] { "good", "best", "nice" };

var searchResults = wordsToSearch
    .Select(word =>
        new
        {
            word,
            phrases = lookup[word].ToArray()
        });

foreach (var result in searchResults)
{
    Console.WriteLine(
        "Word '{0}' can be found in phrases : {1}",
        result.word,
        String.Join(
            ", ",
            result
                .phrases
                .Select(phrase => 
                    String.Format("{0}='{1}'", phrase.index, phrase.phrase))));
}      

它为您提供索引和短语,因此您可以根据需要调整它。

但是,如果您的Collection2 不是由单词组成,而是由短语组成,那么您将需要更强大的东西,比如lucene.net,它可以正确处理全文搜索。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    • 2011-02-10
    相关资源
    最近更新 更多