我有以下的功能,我想知道是否有人能想出更有效率的东西。
它只需拆分内容和搜索字符串,并确定在成为真之前需要匹配多少单词。
例如,
"A dog can run.".ContainsV2("Red Dog Run", 4) = false
"A dog can run.".ContainsV2("Red Dog Run", 2) = true
"A dog can run.".ContainsV2("Red Dog Run") = true
"A dog can run.".ContainsV2("Red Dog Run", MatchAllWords: true) = false/// <summary>
/// Checks to see if any of the words are contained in the string.
/// </summary>
/// <param name="content"></param>
/// <param name="SearchString">Search string</param>
/// <param name="NumberOfMatches">Specify how many words have to match in the search string.
/// This value is automatically dropped when the user searches less words.
/// I.e. NumberOfMatches = 3 and the user searches 'Bob', NumberOfMatches gets set to 1.</param>
/// <param name="MatchAllWords">If set to true, all of the words in the search string must be contained in what's being checked</param>
/// <returns></returns>
public static bool ContainsV2(this string content, string SearchString, int NumberOfMatches = 1, bool MatchAllWords = false)
{
var matches = 0;
var numberOfWords = SearchString.Split(' ').Length;
// Update required number of matches
NumberOfMatches = NumberOfMatches > numberOfWords ?
numberOfWords :
NumberOfMatches;
if (!string.IsNullOrEmpty(content) && !string.IsNullOrEmpty(SearchString))
{
SearchString.Split(' ')
.ToList()
.ForEach(w => //Gets the index of each word after being split
matches += content
.IndexOf(
StripNonAlphaNumeric(w),
StringComparison.OrdinalIgnoreCase
) >= 0 ? 1 : 0
);
}
if (MatchAllWords)
{
return matches == numberOfWords;
}
return matches >= NumberOfMatches;
}发布于 2016-04-05 19:23:35
关于您的代码的几点评论:
方法应该有有意义的名称。您的扩展方法看起来更新(更好?)已经存在的Contains方法的版本,但是扩展方法做的不是原始的。一个更好的,有意义的名字是ContainsWords。
你的论点也可以这样说。在我看来,SearchString并没有涵盖这个论点的意义。wordsToMatch更合适。我重命名了其他参数,就像您在代码中看到的那样。
扩展方法只接受包含要匹配的单词的字符串。为了方便使用,我会添加一个重载,它需要一个单词集合。
下面是我对它的看法:
using System;
using System.Collections.Generic;
using System.Linq;
public static class StringExtensions
{
public static bool ContainsWords(this String source, IEnumerable<String> wordsToMatch, int matchAtLeast = 1, bool matchAll = false)
{
if(wordsToMatch == null)
{
throw new ArgumentNullException();
}
var sourceWords = GetWords(source);
var matches = sourceWords.Intersect(wordsToMatch, StringComparer.CurrentCultureIgnoreCase);
if(matchAll || wordsToMatch.Count() < matchAtLeast)
{
return matches.Count() == sourceWords.Count();
}
return matches.Count() >= matchAtLeast;
}
public static bool ContainsWords(this String source, String wordsToMatch, int matchAtLeast = 1, bool matchAll = false)
{
if(wordsToMatch == null)
{
throw new ArgumentNullException();
}
return source.ContainsWords(GetWords(wordsToMatch), matchAtLeast, matchAll);
}
// Splits string in individual words.
private static IEnumerable<String> GetWords(String source)
{
return source.Split(new [] {' '}, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim('.'));
// Optionally: trim other punctuation.
}
}关于效率的
在您的代码中,将搜索字符串拆分两次。这不是很有效率。接下来,您将对搜索字符串中的每个单词在源字符串上使用IndexOf。这也不是很有效率。我不太擅长算法分析,但我的猜测是,将源和单词分开来匹配,然后在结果数组上应用Intersect是更有效的。
发布于 2016-04-05 19:14:26
这是我的第一篇评论。看看你能做什么!我给你留下了评论。他们总是讨论下面的代码。
将文档标记保持为空是不好的风格。要么没有param标记,要么用适当的描述填充所有内容:
/// <param name="content"></param>
/// <param name="SearchString">Search string</param>
/// <param name="NumberOfMatches">Specify how many words have to match in the search string.在我看来,太多的实施细节:
/// This value is automatically dropped when the user searches less words.
/// I.e. NumberOfMatches = 3 and the user searches 'Bob', NumberOfMatches gets set to 1.</param>自明名称:
/// <param name="MatchAllWords">If set to true, all of the words in the search string must be contained in what's being checked</param>这是不言自明的,删除行:
/// <returns></returns>使用一个更有说服力的名字,比如ContainsWords:
public static bool ContainsV2(this string content, string SearchString, int NumberOfMatches = 1, bool MatchAllWords = false)
{
var matches = 0;
var numberOfWords = SearchString.Split(' ').Length;不要使用空注释,如“设置变量”或“更新值”。更好地解释它,或者省略评论:
// Update required number of matches接线员很难理解,这里没有必要。相反,请在我的评论中使用如下所示:
// if (NumberOfMatches > numberOfWords)
// {
// NumberOfMatches = numberOfWords;
// }
NumberOfMatches = NumberOfMatches > numberOfWords ?
numberOfWords :
NumberOfMatches;您已经拆分了上面的搜索字符串。要么不检查null,要么在开始时执行它:
if (!string.IsNullOrEmpty(content) && !string.IsNullOrEmpty(SearchString))
{这太让人困惑了。降低复杂性和嵌套深度:
SearchString.Split(' ')
.ToList()
.ForEach(w => //Gets the index of each word after being split
matches += content
.IndexOf(
StripNonAlphaNumeric(w),
StringComparison.OrdinalIgnoreCase
) >= 0 ? 1 : 0
);
}而是在函数的开头设置它。这里令人困惑的是:
if (MatchAllWords)
{
return matches == numberOfWords;
}
return matches >= NumberOfMatches;
}https://codereview.stackexchange.com/questions/124848
复制相似问题