通过StartsWith和EndsWith查询通过LINQ选择字符串列表时,如何保持字符串数据以获得最佳性能
本文关键字:字符串 何保持 数据 性能 最佳 列表 EndsWith StartsWith 查询 选择 LINQ | 更新日期: 2023-09-27 18:25:26
现在这个问题很难回答。我有一个类似下面方式的linq查询
var lstSimilars = from similarWords in lstAllWords
where similarWords.StartsWith(srWordLocal)
select similarWords;
foreach (string srVar in lstSimilars)
{
string srTempWord = srVar.Replace(srWordLocal, "");
if (dtWords.ContainsKey(srTempWord) == true)
{
csWords.updateSplitWord(srWordLocal + ";" + srTempWord, dtWords[srVar]);
}
}
lstSimilars = from similarWords in lstAllWords
where similarWords.EndsWith(srWordLocal)
select similarWords;
foreach (string srVar in lstSimilars)
{
string srTempWord = srVar.Replace(srWordLocal, "");
if (dtWords.ContainsKey(srTempWord) == true)
{
csWords.updateSplitWord(srWordLocal + ";" + srTempWord, dtWords[srVar]);
}
}
现在lstAllWords
是一个字符串列表变量,生成方式与类似
List<string> lstAllWords = new List<string>();
for (int i = 0; i < dsWordsSplit.Tables[0].Rows.Count; i++)
{
lstAllWords.Add(dsWordsSplit.Tables[0].Rows[i]["Word"].ToString());
}
我的问题是,我应该如何保存Words数据以获得最佳LINQ选择性能。我的意思是,目前我把它作为一个字符串列表。但我能保持不同的方式并有更好的表现吗?
dtWords
是字典对象
C#C#-4.0 LINQ
如果您只想有效地查找以给定子字符串开头或结尾的单词,那么使用SortedSet将帮助您在O(log(N))时间内做到这一点。
这个想法是把单词放在两个SortedSet
中:
- 一个用于原始单词和
- 另一个表示颠倒的单词
玩具实施:
class WordSet {
public WordSet(IEnumerable<string> words) {
m_OriginalWords = new SortedSet<string>(words);
m_ReverseWords = new SortedSet<string>(words.Select(ReverseString));
}
/// <summary>
/// Finds all words that start with given prefix.
/// </summary>
public IEnumerable<string> FindPrefix(string prefix) {
return FindImp(m_OriginalWords, prefix);
}
/// <summary>
/// Finds all words that end with the given suffix.
/// </summary>
public IEnumerable<string> FindSuffix(string suffix) {
return FindImp(m_ReverseWords, ReverseString(suffix)).Select(ReverseString);
}
static IEnumerable<string> FindImp(SortedSet<string> word_set, string s) {
if (s.CompareTo(word_set.Max) <= 0) {
foreach (string word in word_set.GetViewBetween(s, word_set.Max)) {
if (!word.StartsWith(s))
break;
yield return word;
}
}
}
static string ReverseString(string src) {
return new string(src.Reverse().ToArray());
}
readonly SortedSet<string> m_OriginalWords;
readonly SortedSet<string> m_ReverseWords;
}
class Program {
static void TestImp(string s, IEnumerable<string> words) {
Console.Write(s);
foreach (var word in words) {
Console.Write(''t');
Console.Write(word);
}
Console.WriteLine();
}
static void TestPrefix(WordSet word_set, string prefix) {
TestImp(prefix, word_set.FindPrefix(prefix));
}
static void TestSuffix(WordSet word_set, string suffix) {
TestImp(suffix, word_set.FindSuffix(suffix));
}
static void Main(string[] args) {
var word_set = new WordSet(
new[] {
"a",
"b",
"ba",
"baa",
"bab",
"bba",
"bbb",
"bbc",
}
);
Console.WriteLine("Prefixes:");
TestPrefix(word_set, "a");
TestPrefix(word_set, "b");
TestPrefix(word_set, "ba");
TestPrefix(word_set, "bb");
TestPrefix(word_set, "bc");
Console.WriteLine("'nSuffixes:");
TestSuffix(word_set, "a");
TestSuffix(word_set, "b");
TestSuffix(word_set, "ba");
TestSuffix(word_set, "bb");
TestSuffix(word_set, "bc");
}
}
此打印:
Prefixes:
a a
b b ba baa bab bba bbb bbc
ba ba baa bab
bb bba bbb bbc
bc
Suffixes:
a a baa ba bba
b b bab bbb
ba ba bba
bb bbb
bc bbc
如果你也必须搜索中缀,那么以上是不够的——你需要一个后缀树或数组,但这不是一件容易的事,可以有效地正确实现和。
顺便说一句,如果数据恰好在数据库中,你可以让DBMS做基本上相同的事情:
- 创建与原始单词列相反的计算列或虚拟列
- 索引原始单词列和反向单词列(或者,如果DBMS支持,则使用基于函数的索引)
- 查询前缀为:
ORIGINAL_WORD_COLUMN LIKE 'pefix%'
- 后缀为:
REVERSED_WORD_COLUMN LIKE 'reversed_suffix%'
字符串列表应该具有足够的性能,可以从中进行选择,但您要添加一些装箱/取消装箱操作,方法是将其选择到var
中,然后对其进行迭代。为了提高性能,您可以使用强类型List<string>
作为LINQ查询结果的接收者,但它可能只在非常的大型数据集中才明显。