C# 获取SortedDictionary中的最后一个元素

C# 获取SortedDictionary中的最后一个元素,c#,collections,sorteddictionary,C#,Collections,Sorteddictionary,我明白了 如何获取.Net 3.5中SortedDictionary中的最后一个元素。您可以使用SortedDictionary.Values.last() 或者如果您想要键和值 SortedDictionary.Last(); 您可以使用LINQ: var lastItem = sortedDict.Values.Last(); 您还可以获取最后一个密钥: var lastkey = sortedDict.Keys.Last(); 您甚至可以获取最后一个键值对: var lastKeyV

我明白了


如何获取.Net 3.5中SortedDictionary中的最后一个元素。

您可以使用
SortedDictionary.Values.last()

或者如果您想要键和值

SortedDictionary.Last();
您可以使用LINQ:

var lastItem = sortedDict.Values.Last();
您还可以获取最后一个密钥:

var lastkey = sortedDict.Keys.Last();
您甚至可以获取最后一个键值对:

var lastKeyValuePair = sortedDict.Last();
这将为您提供一个具有
Key
Value
属性的
KeyValuePair


请注意,如果字典为空,这将引发异常;如果您不想这样做,请调用
LastOrDefault

Last
扩展方法将为您提供结果,但它必须枚举整个集合才能达到目的。很遗憾,
SortedDictionary
没有公开
Min
Max
成员,特别是考虑到它内部有一个
SortedSet
支持,它有
Min
Max
属性

如果不需要O(n),您有几个选项:

  • 切换到
    SortedList
    。出于某种原因,BCL在默认情况下不会打包此文件。您可以使用索引器在O(1)时间内获取最大(或最小)值。使用扩展方法进行扩展会很好

    //Ensure you dont call Min Linq extension method.
    public KeyValuePair<K, V> Min<K, V>(this SortedList<K, V> dict)
    {
        return new KeyValuePair<K, V>(dict.Keys[0], dict.Values[0]); //is O(1)
    }
    
    //Ensure you dont call Max Linq extension method.
    public KeyValuePair<K, V> Max<K, V>(this SortedList<K, V> dict)
    {
        var index = dict.Count - 1; //O(1) again
        return new KeyValuePair<K, V>(dict.Keys[index], dict.Values[index]);
    }
    
    这是O(logn)。没有文档,但我检查了代码

  • 使用fiddly反射访问作为
    SortedDictionary
    类的私有成员的支持集,并调用
    Min
    Max
    属性。可以依靠表达式编译委托并缓存它以提高性能。这样做是一个非常糟糕的选择。真不敢相信我提出了这个建议

  • 依赖于其他实现,例如。他们已经和

  • 分类列表

    list[ Keys[Keys.Count - 1] ];  // returns the last entry in list
    

    正如人们已经指出的,Last扩展将枚举整个集合,它对性能的影响可能是致命的。 仅从SortedAct中移除10000个最后的元素,就比SortedSet上的类似操作花费了更多的时间

  • 分拣集移除已用毫秒:8

  • 分拣数据删除时间:3697毫秒

    //在下面的代码中,ss是SortedSet,sd是SortedDictionary,两者都包含相同的10000个元素

     sw.Start();
     while (ss.Count != 0)
     {
         ss.Remove(ss.Max);
     }
    
     sw.Stop();
     Console.WriteLine("SortedSet Removal Elapsed ms : {0}", sw.ElapsedMilliseconds);
    
     sw.Reset();
    
     sw.Start();
     while (sd.Count != 0)
     {
         sd.Remove(sd.Keys.Last());
     }
    
     sw.Stop();
     Console.WriteLine("Dict Removal Elapsed ms : {0}", sw.ElapsedMilliseconds);
    

  • 这些方法可能触发枚举。我想知道是否有任何方法可以在不进行枚举的情况下获取最后一个元素(或任何位置索引中的元素)?因为SortedDictionary被分类成一棵树,所以理论上它是可能的?@RolandPihlakas:理论上是的。在实践中,我不这么认为。对于C++背景的人来说,这是很难接受的。仅仅为了得到最后一个元素而枚举整个已排序字典的效率低得令人绝望。有没有更强大的C#收藏库?@ThunderGr:没有;它没有索引器。@Lander:一旦删除元素,索引器就会完全失效。可能需要重新排列这些选项,以便更好的选项位于顶部,而不是像我想的那样,将它们放在顶部,是您想到它们的顺序。您将如何为第二个选项实现索引器/
    TryGetValue
    ?@code如果您是对的,那么它就没用了。NET中的集合没有公开获取实际引用的方法,这是令人遗憾的。我应该编辑答案。这在GitHub中仍然是一个悬而未决的问题:。似乎出于某种原因,他们不喜欢向现有集合类型添加新功能。
     sw.Start();
     while (ss.Count != 0)
     {
         ss.Remove(ss.Max);
     }
    
     sw.Stop();
     Console.WriteLine("SortedSet Removal Elapsed ms : {0}", sw.ElapsedMilliseconds);
    
     sw.Reset();
    
     sw.Start();
     while (sd.Count != 0)
     {
         sd.Remove(sd.Keys.Last());
     }
    
     sw.Stop();
     Console.WriteLine("Dict Removal Elapsed ms : {0}", sw.ElapsedMilliseconds);