【问题标题】:Return min value of key as a property of the collection返回键的最小值作为集合的属性
【发布时间】:2017-02-22 00:31:34
【问题描述】:

我定义了一个从 Dictionary 继承的名为 Diversion 的新类,用于保存一组 DateTime 键和相关的 int 值。

我想返回最早的键值和平均 int 值作为类的属性(假设它已被填充)。

有没有更有效的方法来遍历字典?定义类的实例时如何引用它?

提前感谢所有帮助!

   public class Diversion : Dictionary<DateTime, int>
{
    private DateTime _starttime;
    private decimal _avg;

    public DateTime Starttime {
        get {
            if (Diversion.count > 0) {
                _starttime = new DateTime(2999,1,1);
                foreach(KeyValuePair<DateTime, int> de in Diversion) {
                    if (de.key < _starttime) _starttime = de.key;
                }
                return _starttime;
            }
            else    return; 
         }
    }

    public DateTime AvgVal {
        get {
            if (Diversion.count > 0) {
                _avg = 0;
                foreach(KeyValuePair<DateTime, int> de in Diversion) {
                    _avg = _avg + de.value;
                }
                _avg = _avg / Diversion.count;
                return _avg;
            }
            else    return; 
         }
    }       

    public Diversion() {}
}

【问题讨论】:

  • this 是你的朋友
  • 为什么不在字典被操纵时跟踪这些东西,而不是在需要时计算它们

标签: c#


【解决方案1】:

是的。您可以使用 LINQ 隐藏您的复杂性。
Dictionary.Keys
Enumerable.Min Enumerable.Average

public DateTime Starttime 
{
    get 
     {
        if (this.Count > 0) 
        {
             return this.Keys.Min();    
        }
        return new DateTime(2999,1,1);;
     }
}

public DateTime AvgVal 
{
    get
    {
        if (this.Count > 0) 
           return this.Values.Average();  
        else    
           return DateTime.MinValue; //something must be returned.
   }
}

当您扩展任何类(本例中为字典)时,您可以使用this 关键字访问基类(和当前类)的所有属性。在您的代码中,您使用的是基类名称,这是不正确的。

【讨论】:

  • 您的AvgVal 属性返回了错误的值,它应该是这些值的平均值。另请注意,OP 代码的主要问题是它们使用的是Diversion 而不是this,因此您可能需要强调这一点。
【解决方案2】:

而不是继承 Dictionary&lt;TK,TV&gt;,您可以实现 IDictionary&lt;TK,TV&gt; 包装一个实际的字典。这样您就可以控制对包装字典的访问,保持当前的最小值和总数:

public class Diversion : IDictionary<DateTime,int> {
    private decimal currentTotal;
    private SortedSet<DateTime> keys = new SortedSet<DateTime>();
    private Dictionary<DateTime,int> dict = new Dictionary<DateTime,int>();
    ...
    public decimal AvgVal {
        get {
            if (dict.Count == 0) throw InvalidOperationException();
            return currentTotal / dict.Count;
        }
    }
    public DateTime StartTime {
        get {
            if (dict.Count == 0) throw InvalidOperationException();
            return keys.Min;
        }
    }
}

您将通过将调用转发到包装好的dict 来实现IDictionary&lt;DateTime,int&gt; 的所有方法,但有三个例外:

  • 添加新条目的操作需要将密钥添加到keys,并将currentTotal增加value
  • 通过key移除条目的操作需要移除key并减少currentTotal,并且
  • 替换特定键条目的操作需要从currentTotal 中减去旧值,并将新值添加到结果中。

这将使您的附加操作AvgValStartTime 立即完成,而不管集合的当前大小。另一方面是实现需要维护平衡的键树,因此所有变异操作将变为 O(log2n)。

【讨论】:

    猜你喜欢
    • 2021-07-26
    • 2021-06-11
    • 2011-04-19
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多