用于对列表<;int>;

本文关键字:int gt lt 用于 列表 | 更新日期: 2023-09-27 18:19:46

我为绘图应用程序保留了一个滚动累加器,其中一个功能是提供样本的运行平均值。

累加器的大小是可变的,但基本上最终目标是这样实现的。

累加器类(丑陋但实用)

    public class accumulator<t>
    {
        private int trim;
        List<t> _points = new List<t>();
        List<string> _labels = new List<string>();
        List<t> _runAvg = new List<t>();
        List<t> _high = new List<t>();
        List<t> _low = new List<t>();
        public List<t> points { get { return _points; } }
        public List<string> labels { get { return _labels; } }
        public List<t> runAvg { get { return _runAvg; } }
        public List<t> high { get { return _high; } }
        public List<t> low { get { return _low; } }
        public delegate void onChangeHandler(accumulator<t> sender, EventArgs e);
        public event onChangeHandler onChange;
        public accumulator(int trim)
        {
            this.trim = trim;
        }
        public void add(t point, string label)
        {
            if (_points.Count == trim)
            {
                _points.RemoveAt(0);
                _labels.RemoveAt(0);
                _runAvg.RemoveAt(0);
                _high.RemoveAt(0);
                _low.RemoveAt(0);
            }
            _points.Add(point);
            _labels.Add(label);
            if (typeof(t) == typeof(System.Int32))
            {
                int avg = 0;
                if (_high.Count == 0)
                {
                    _high.Add(point);
                }
                else
                {
                    t v = (Convert.ToInt32(point) > Convert.ToInt32(_high[0])) ? point : _high[0];
                    _high.Clear();
                    for (int i = 0; i < _points.Count; i++) _high.Add(v);
                }
                if (_low.Count == 0)
                {
                    _low.Add(point);
                }
                else
                {
                    t v = (Convert.ToInt32(point) < Convert.ToInt32(_low[0])) ? point : _low[0];
                    _low.Clear();
                    for (int i = 0; i < _points.Count; i++) _low.Add(v);
                }
                foreach (t item in _points) avg += Convert.ToInt32(item);
                avg = (avg / _points.Count);
                _runAvg.Add((t)(object)avg);
                //_runAvg.Add((t)(object)_points.Average(a => Convert.ToInt32(a)));
            }
            if (typeof(t) == typeof(System.Double))
            {
                double avg = 0;
                if (_high.Count == 0)
                {
                    _high.Add(point);
                }
                else
                {
                    t v = (Convert.ToDouble(point) > Convert.ToDouble(_high[0])) ? point : _high[0];
                    _high.Clear();
                    for (int i = 0; i < _points.Count; i++) _high.Add(v);
                }
                if (_low.Count == 0)
                {
                    _low.Add(point);
                }
                else
                {
                    t v = (Convert.ToDouble(point) < Convert.ToDouble(_low[0])) ? point : _low[0];
                    _low.Clear();
                    for (int i = 0; i < _points.Count; i++) _low.Add(v);
                }
                foreach (t item in _points) avg += Convert.ToDouble(item);
                avg = (avg / _points.Count);
                _runAvg.Add((t)(object)avg);
                //_runAvg.Add((t)(object)_points.Average(a => Convert.ToDouble(a)));
            }
            onChangeHappen();
        }
        private void onChangeHappen()
        {
            if (onChange != null) onChange(this, EventArgs.Empty);
        }
    }

正如你所看到的,本质上我想保持一个运行平均值,一个高/低标记(具有相同的数据点计数,因此它直接绑定到扩展序列类中的图表控件)

平均值是我认为最让我头疼的,必须将列表中的每个元素添加到一个和/除以计数中,这当然是实现平均值的方法,但循环是实现这一点的最有效方法吗?

我尝试了一个lambda表达式(注释掉了),但在某种程度上认为它也必须这样做。(有点像使用泛型列表VS数组,我认为它必须在某个地方重新声明一个数组并四处移动元素,但它可能比我做的更有效,所以为了方便起见,让它做吧)

最终目标和最终问题是,给出一个通用值列表。。。

对整个列表求平均值的最有效方法。

*注意:我确实意识到输入int/foats的迂腐性质,这是,因为在我无法控制的这个类的使用者中进行类型检查,它实际上看起来是不是double/int,否则我会将其全部视为float;)

提前感谢。。。

用于对列表<;int>;

保持运行平均值实际上很容易。你不需要每次都对整个列表求和,因为你已经有了!

一旦你有了当前的平均值(从你的循环),你只需要做以下事情:

((oldAverage * oldCount) + newValue) / newCount

这将为您提供包含新值的旧集合的平均值。

要获得初始平均值,请考虑使用LINQ:中的Average函数

double average = listOfInts.Average();