c# – 为不需要的字符串过滤IEnumerable

编辑:我收到了一些非常好的建议,我将尝试通过它们并在某些时候接受答案

我有一个很大的字符串列表(800k),我希望尽快过滤掉不需要的单词列表(最终亵渎但可能是任何东西).

我最终希望看到的结果将是一个列表,如

Hello,World,My,Name,Is,Yakyb,Shell

会成为

World,My,Name,Is,Yakyb

经过检查后

Hell,Heaven.

到目前为止我的代码是

 var words = items
            .Distinct()
            .AsParallel()
            .Where(x => !WordContains(x, WordsUnwanted));

public static bool WordContains(string word, List<string> words)
    {
        for (int i = 0; i < words.Count(); i++)
        {
            if (word.Contains(words[i]))
            {
                return true;
            }
        }
        return false;
    }

目前这需要大约2.3秒(9.5 w / o并行)来处理800k字,这对于一次性来说并不是什么大不了的事.但是,学习过程是否有更快的处理方式?

不需要的单词列表长100个单词
没有一个词包含标点符号或空格

>采取措施删除所有列表中的重复项
>步骤查看是否更快地使用数组(不是)有趣地将参数单词更改为字符串[]使其慢25%
>步骤添加AsParallel()将时间缩短到~2.3秒

最佳答案 尝试使用名为Except的方法.

http://msdn.microsoft.com/en-AU/library/system.linq.enumerable.except.aspx

var words = new List<string>() {"Hello","Hey","Cat"};
var filter = new List<string>() {"Cat"};

var filtered = words.Except(filter);

还怎么样:

var words = new List<string>() {"Hello","Hey","cat"};
var filter = new List<string>() {"Cat"};
// Perhaps a Except() here to match exact strings without substrings first?
var filtered = words.Where(i=> !ContainsAny(i,filter)).AsParallel();    
// You could experiment with AsParallel() and see 
// if running the query parallel yields faster results on larger string[]
// AsParallel probably not worth the cost unless list is large
public bool ContainsAny(string str, IEnumerable<string> values)
{
   if (!string.IsNullOrEmpty(str) || values.Any())
   {
       foreach (string value in values)
       {
             // Ignore case comparison from @TimSchmelter
             if (str.IndexOf(value, StringComparison.OrdinalIgnoreCase) != -1) return true;

             //if(str.ToLowerInvariant().Contains(value.ToLowerInvariant()))
             // return true;
       }
   }

   return false;
}
点赞