C# 使用SortedDictionary TakeWhile返回空

C# 使用SortedDictionary TakeWhile返回空,c#,linq-to-objects,sorteddictionary,C#,Linq To Objects,Sorteddictionary,TakeWhile扩展方法的工具提示中有以下注释:“元素的索引用于谓词函数的逻辑”。请注意,此工具提示在普通工具提示中不可见,但仅在变量sortedDictionary的列表成员的intellisense列表的工具提示中可见 var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey)); var last= sortedDictionary.Last(kv => kv.Key.ToS

TakeWhile
扩展方法的工具提示中有以下注释:“元素的索引用于谓词函数的逻辑”。请注意,此工具提示在普通工具提示中不可见,但仅在变量
sortedDictionary
的列表成员的intellisense列表的工具提示中可见

var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
var last= sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
var range = sortedDictionary.TakeWhile(kv => kv.Key.ToString().StartsWith(searchkey));
这正是与
SortedDictionary
相结合所要寻找的

var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
var last= sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
var range = sortedDictionary.TakeWhile(kv => kv.Key.ToString().StartsWith(searchkey));
第一个和最后一个项目已找到且正确,但我的收集范围为空。
这里怎么了?我期望一个范围内的所有项目之间的第一和最后包括他们

我仍然可以使用first和last找到范围,但是
TakeWhile
使用索引,而
first
last
显然不使用索引

编辑:“使用索引”与排序无关,但您可以在查询中使用索引。例如,当我将
SortedDictionary
替换为
SortedList
时,我可以:

int ix1 = sortedList.IndexOfKey(first.Key);
int ix2 = sortedList.IndexOfKey(last.Key);
var range = sortedList.SkipWhile((x, i) => i < ix1).TakeWhile((x, i) => i <= ix2);
var range = sortedList.SkipWhile(x => !x.Key.ToString().StartsWith(searchkey))
                      .TakeWhile(x => x.Key.ToString().StartsWith(searchkey));

我必须测试哪个方法更快,还必须测试Where查询。

您阅读的工具提示是针对一个重载的,该重载的谓词有一个Int32作为参数

你介意发布一些代码,看看它为什么返回空范围吗?。以下代码按预期工作(我复制/粘贴了您的代码)

var sortedDictionary=new sortedDictionary();
var searchkey=“测试”;
添加(“test1”、“value”);
添加(“test2”,“value”);
添加(“test3”、“value”);
添加(“test4”,“value”);
var first=sortedDictionary.first(kv=>kv.Key.ToString().StartsWith(searchkey));
var last=sortedDictionary.last(kv=>kv.Key.ToString().StartsWith(searchkey));
var range=sortedDictionary.TakeWhile(
kv=>kv.Key.ToString().StartsWith(searchkey));
foreach(范围内的var c)
{
控制台写入线(c);
}
Console.ReadKey();
TakeWhile()
将获取从序列开头开始的项,只要它们都满足谓词。如果第一项未通过谓词,则结果为空。您正在谈论的描述来自包含索引(您不使用该索引)的

只需正常过滤项目,它应该会产生您期望的范围(由于排序)


如果序列中的第一个元素与谓词不匹配,则该方法将退出:

将序列中的元素返回为 只要指定的条件为真

该方法将采用与谓词匹配的第一个元素:

返回数组中的第一个元素 满足指定条件的序列 状况

与第一个方法相反,该方法将采用与谓词匹配的最后一个元素:

返回序列的最后一个元素 满足特定条件的

我猜TakeWhile很早就退出了,因为它们没有与迭代开始时的条件匹配的元素

如果需要示例中第一个和最后一个元素之间的元素范围(包括第一个和最后一个项目),请尝试以下操作:

var range = sortedDictionary.SkipWhile( x => !x.Equals( first ) )
  .TakeWhile( x => !x.Equals( last ) )
  .Concat( new SortedDictionary<string, string> { { last.Key, last.Value } } );
var range=sortedDictionary.SkipWhile(x=>!x.Equals(第一个))
.TakeWhile(x=>!x.Equals(最后一个))
.Concat(新的SortedDictionary{{last.Key,last.Value});

或者,您可以像我一样仔细考虑这一点,使用中的
Where
方法使用更简单的方法。

代码示例中的
方法是标准的
可枚举方法吗?或者你是想用
Where
?@Metro:啊,是的,我的意思是
Where()
。谢谢。这是可行的,但我只是尝试使用排序索引,这个查询可能从索引0开始,当关键字不是以searchkey开始时,它将继续扫描列表-或者?@Gerard:如果您想查看整个列表,那么使用
Last()
将不会有帮助。它将遍历整个列表,因为它必须确保它具有满足谓词的最后一项。为了获得最佳解决方案,将更新中包含的
SkipWhile()
TakeWhile()
一起使用是更好的方法。Helas:添加(“a”,“value”)作为命令的第一项。范围将为空。我猜“如果序列中的第一个元素与谓词不匹配,那么TakeWhile方法将退出”您的猜测是正确的,+1表示一个非常好的查询。我将尝试它是否比where查询更快。
var range = sortedDictionary.SkipWhile( x => !x.Equals( first ) )
  .TakeWhile( x => !x.Equals( last ) )
  .Concat( new SortedDictionary<string, string> { { last.Key, last.Value } } );