使用SortedDictionary TakeWhile返回空

时间:2011-02-14 00:14:08

标签: c# linq-to-objects sorteddictionary

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

这正是与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));

找到第一个和最后一个项目并且正确,但我的收藏范围是空的 这有什么不对?我期望一个范围包括第一个和最后一个之间的所有项目,包括它们。

我仍然可以使用第一个和最后一个找到范围,但TakeWhile使用索引而FirstLast显然不会。

编辑:“使用索引”原来与排序无关,但您可以在查询中使用索引。例如。当我用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);

还可以使用SortedDictionary

var range = sortedList.SkipWhile(x => !x.Key.ToString().StartsWith(searchkey))
                      .TakeWhile(x => x.Key.ToString().StartsWith(searchkey));

我将不得不测试哪种方法更快,还必须测试Where查询。

3 个答案:

答案 0 :(得分:1)

TakeWhile()将从序列的开头开始,只要它们都满足谓词。如果第一项未通过谓词,则结果为空。您所谈论的描述来自overload,其中包含一个索引(您未使用)。

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

var range = sortedDictionary.Where(kv => kv.Key.ToString().StartsWith(searchkey));

答案 1 :(得分:1)

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

  

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

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

  

返回a中的第一个元素   满足指定的序列   条件

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

  

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

我猜测TakeWhile正在提前退出,因为它们在迭代开始时没有符合条件的元素。

如果你想要你的例子中第一个和最后一个元素之间的元素范围(包括第一个和最后一个项目),那么试试这个:

var range = sortedDictionary.SkipWhile( x => !x.Equals( first ) )
  .TakeWhile( x => !x.Equals( last ) )
  .Concat( new SortedDictionary<string, string> { { last.Key, last.Value } } );

或者你不能像我一样过度思考这个问题,并使用Where方法中的{{1}}方法使用更简单的方法。

答案 2 :(得分:0)

您阅读的工具提示是针对重载的,其谓词的Int32为参数MSDN Link

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

        var sortedDictionary = new SortedDictionary<string, string>();
        var searchkey = "test";
        sortedDictionary.Add("test1", "value");
        sortedDictionary.Add("test2", "value");
        sortedDictionary.Add("test3", "value");
        sortedDictionary.Add("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 in range)
        {
            Console.WriteLine(c);
        }
        Console.ReadKey();