【问题标题】:Get the last element in a dictionary?获取字典中的最后一个元素?
【发布时间】:2010-11-04 07:51:05
【问题描述】:

我的字典:

Dictionary<double, string> dic = new Dictionary<double, string>();

如何返回字典中的最后一个元素?

【问题讨论】:

  • 定义最后一个元素:最后插入?最后排序的元素?
  • 有趣的是有多少人支持错误的答案!
  • subprime,看看我的帖子——我提到了 OrderedDictionary 集合类——这可能是你最好的选择。普通字典不保留广告订单信息。
  • @LBushkin- 这就是为什么我建议创建一个包装类。
  • RichardOD 的包装类看起来很到位。

标签: c# .net dictionary


【解决方案1】:

如果你只想要这个值,这应该可以工作(假设你可以使用 LINQ):

dic.Values.Last()

【讨论】:

  • 您也可以使用“dic.Last()”来获取整个键/值对。他们应该工作相同
【解决方案2】:

你可以使用:

dic.Last()

但是字典实际上并没有最后一个元素(里面的对没有以任何特定的方式排序)。最后一项总是相同的,但它可能是哪个元素并不明显。

【讨论】:

    【解决方案3】:

    使用 .Net 3.5:

    string lastItem = dic.Values.Last()
    string lastKey = dic.Keys.Last()
    

    ...但请记住,字典没有排序,因此您不能指望值将保持相同的顺序。

    【讨论】:

      【解决方案4】:

      你说的最后是什么意思?你的意思是最后的增值吗?

      Dictionary&lt;TKey,TValue&gt; 类是一个无序集合。添加和删​​除项目可以更改被认为是第一个和最后一个元素的内容。因此,无法添加 Last 元素。

      有一个以SortedDictionary&lt;TKey,TValue&gt; 形式提供的有序字典类。但这将根据键的比较而不是添加值的顺序进行排序。

      编辑

      有人提到使用以下 LINQ 样式方法

      var last = dictionary.Values.Last();
      

      使用这种方法时要非常小心。它将返回 Values 集合中的最后一个值。这可能是也可能不是您添加到字典中的最后一个值。它很可能不会像现在这样。

      【讨论】:

      • 赞成关于不使用 LINQ 样式方法的警告,因为它不返回子质所需的内容。
      • 虽然没有通用版本,但 System.Collection.Specialized 命名空间中有一个 OrderedDictionary,用于维护插入顺序中的项目。
      • @subprime,在这种情况下使用 LastOrDefault 而不是 Last。
      【解决方案5】:

      如果您使用的是 .NET 3.5,请查看:

       dic.Keys.Last()
      

      但是,如果您想要一个可预测的顺序,请使用:

      IDictionary<int, string> dic = new SortedDictionary<int, string>();
      

      【讨论】:

      • 每次调用“Last()”都会返回相同的结果,直到插入或“Add()”,对吗?在哪一点上可能会有所不同?
      • 我相信是这样,但由于它是一个无序的集合,最后添加的可能在集合中间的某个地方。我不确定它是如何在内部实现的,或者 Last() 实际返回什么。对内部有更多了解的人必须回答这个问题。释放飞碟信号。
      【解决方案6】:

      字典是无序的集合——因此,没有第一个或最后一个元素的概念。如果您正在寻找一个行为类似于字典但保持项目插入顺序的类,请考虑使用OrderedDictionary

      如果您正在寻找对项目进行排序的集合,请考虑使用SortedDictionary&lt;TKey,TValue&gt;

      如果您有一个现有的字典,并且您正在寻找给定排序顺序的“最后一个”元素,则可以使用 linq 对集合进行排序,例如:

      myDictionary.Values.OrderBy( x => x.Key ).Last();
      

      谨慎使用Dictionary.Keys.Last() - 虽然键列表使用默认的IComparer 对键类型进行排序,但您获得的值可能不是您期望的值。

      【讨论】:

        【解决方案7】:

        考虑创建一个自定义集合,其中包含自定义集合的Add 方法中的引用。这将根据您的要求设置一个包含最后添加的键/值(或两者)的私有字段。

        然后有一个返回 this 的 Last() 方法。这是一个概念证明类来说明我的意思(请不要敲缺乏接口实现等 - 它是示例代码):

        public class LastDictionary<TKey, TValue>
        {
            private Dictionary<TKey, TValue> dict;
        
            public LastDictionary()
            {
                dict = new Dictionary<TKey, TValue>();
            }
        
            public void Add(TKey key, TValue value)
            {
                LastKey = key;
                LastValue = value;
                dict.Add(key, value);
            }
        
            public TKey LastKey
            {
                get; private set;
            }
        
            public TValue LastValue
            {
                get; private set;
            }
        }
        

        【讨论】:

        • 聪明 :-) 您可以通过使用带有私有 setter 和公共 getter 的自动属性来使其更简洁。
        • @Metro Smurf- 非常正确,谢谢。我已经更新了代码以包含这些 - 我相信它使示例更易于阅读。
        • 更好的方法是从 Dictionary 继承,然后重写 Add 方法,您将在其中设置添加的属性,然后调用 base.Add(key,价值)。手动委派 Dictionary 的所有功能将为您省去很多麻烦。
        • @Sprite- 是的,继承字典会是更好的方法,除了 Add 不是虚拟的,所以你有一个问题
        【解决方案8】:

        来自docs

        为了枚举的目的,每个项目 在字典中被视为 KeyValuePair 结构表示一个 价值和它的关键。 顺序 返回的项目是未定义的

        所以,我认为您不能依靠 Dictionary 返回最后一个元素。

        使用另一个集合。也许SortedDictionary ...

        【讨论】:

          【解决方案9】:

          字典并不意味着按顺序访问,所以 first, last 没有任何意义。您想要由最高键索引的值吗?

          Dictionary<double, string> dic = new Dictionary<double, string>();
          double highest = double.MinValue;
          string result = null;
          foreach(double d in dic.keys)
          {
             if(d > highest)
             {
                result = dic[d];
                highest = d;
             }
          }
          

          【讨论】:

            【解决方案10】:

            而不是使用:

            Dictionary<double, string>
            

            ...你可以使用:

            List<KeyValuePair<double, string>>
            

            这将允许您使用索引器按顺序而不是按键访问元素。

            【讨论】:

              【解决方案11】:

              我知道这个问题太老了,无法获得任何支持,但我不喜欢任何答案,因此将发布我自己的答案,希望为未来的读者提供另一种选择。

              假设您想要字典中的最高键值,而不是最后插入的:

              以下在 .NET 4.0 上对我不起作用

              myDictionary.Values.OrderBy( x => x.Key ).Last();
              

              我怀疑问题是'x'代表字典中的一个值,而一个值没有键(字典存储键,字典值没有)。我也可能在使用该技术时犯了一个错误。

              无论哪种方式,这种解决方案对于大型词典来说会很慢,对于 CS 人员来说可能 O(n log n),因为它对整个词典进行排序只是为了得到一个条目。这就像为了找到一部特定的电影而重新排列您的整个 DVD 收藏。


              var lastDicVal = dic.Values.Last();
              

              被认为是一个坏主意。在实践中,此解决方案可能会返回添加到字典中的最后一个值(不是最高键值),但在软件工程术语中这是没有意义的,不应依赖。即使它在永恒的剩余时间里每次都有效,它也代表了你代码中的一个定时炸弹,它取决于库的实现细节。


              我的解决方法如下:

              var lastValue = dic[dic.Keys.Max()];
              

              Keys.max() 函数比排序 O(n) 而不是 O(n log n) 快得多。 如果性能足够重要以至于 O(n) 太慢,则可以在用于替换 dic.Keys.Max() 的单独变量中跟踪最后插入的键,这将使整个查找尽可能快,或者 O(1)。

              注意:使用 double 或 float 作为键不是最佳实践,并且可能会产生超出本文范围的令人惊讶的结果。在浮点/双精度值的上下文中阅读“epsilon”。

              【讨论】:

                【解决方案12】:

                您可以通过 Count 属性访问任何 Collection 对象的最后一个元素,而不是像大多数其他答案所建议的那样使用 Linq(有关详细信息,请参阅 ICollection.Count Property)。

                有关如何使用 count 访问任何集合(包括字典)中的最终元素的示例,请参见此处的代码:

                Dictionary<double, string> dic = new Dictionary<double, string>();
                var lastElementIndex = dic.Count - 1;
                var lastElement = dic[lastElementIndex];
                

                请记住,这会返回最后一个 VALUE,而不是键。

                【讨论】:

                • 这段代码完全是错误的。字典是无序的,并且没有接受索引的索引器。这段代码只能编译,因为字典有一个双精度作为键,因此只有一个接受双精度的索引器。而且由于 int 可以隐式转换为 double,因此您的第三行仅在 int 被转换为 double 时才有效。这将返回与等于 (double)(dic.Count - 1) 的键相对应的值,而不是最后一项(并且具有该键的值可能不存在,在这种情况下,您会得到一个异常而不是一个错误的值)。
                • 您的评论仅适用于 IList 或 IReadOnlyList ,它们确实定义了一个在接口中采用 int 索引的索引器。 ICollection 没有。它们还包含取自 ICollection 接口的 Count 属性。但这本身是不够的,因为 Dictionary 既不实现 IList 也不实现 IReadOnlyList
                猜你喜欢
                • 2016-07-04
                • 1970-01-01
                • 2012-02-11
                • 2012-04-02
                • 2012-12-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-11-30
                相关资源
                最近更新 更多