如何获得符合标准的通用列表的元素的平均值?

我想重新创建一个excel函数AVERAGEIF的通用版本。 它定义如下:

返回满足给定条件的范围内所有单元格的平均值(算术平均值)

我的问题是我不知道如何定义通用平均函数的类型签名。 以下是我所拥有的几乎可以工作的代码。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsTestApp { class Program { static void Main(string[] args) { var dl = new List() { 10, 10, 0, 0 }; var bl = new List() { true, true, false, false }; Func criteria = c => c == true; Console.Out.WriteLine(AVERAGEIF(dl, bl, criteria)); Console.In.Read(); } static T1 AVERAGEIF(List average_range, List criteria_range, Func applyCriteria) { var cl1 = new List<Container>(); foreach (var cl in average_range) { cl1.Add(new Container(cl)); } var cl2 = new List<Container>(); foreach (var cl in criteria_range) { cl2.Add(new Container(cl)); } List<Container> result = new List<Container>((from d in cl1 join b in cl2 on d.Id equals b.Id where applyCriteria(b.Value) select new Container { Value = d.Value, }).ToList<Container>()); var ret = result.Average(s => s.Value); // // return ret; return default(T1); } } class Container { private static uint count = 0; public Container() : base() { count++; this.Id = count; } public Container(T t) : this() { this.Value = t; } public T Value { get; set; } public uint Id { get; private set; } } class ContainerList : List<Container> { List<Container> m_list; public ContainerList() : base() { this.m_list = new List<Container>(); } public ContainerList(List l) : this() { foreach (var li in l) { this.m_list.Add(new Container(li)); } } public ContainerList(List<Container> l) : this() { this.m_list = l; } public T Average(Func<Container, T> selector) { T ret = default(T); if (typeof(T) == typeof(double)) ret = (T)(object)(double)0.0; else if (typeof(T) == typeof(decimal)) ret = (T)(object)(decimal)0.0; else ret = default(T); return ret; } } } 

我想重新创建一个excel函数AVERAGEIF的通用版本

你为什么不只使用LINQ?

 var average = collection.Where(x => x.Something) .Average(x => x.SomeProperty); 

请注意,如果没有匹配的元素,这将抛出exception。 如果你不想那样,你可以使用:

 var average = collection.Where(x => x.Something) .DefaultIfEmpty() .Average(x => x.SomeProperty); 

目前尚不清楚为什么要为此创建单独的方法。

以下是对我有用的答案:

 public double AVERAGEIF(IEnumerable average_range, IEnumerable criteria_range, Func criteria) { var t1andt2 = average_range.Zip(criteria_range, (l, r) => Tuple.Create(l, r)); return t1andt2.Where(x => criteria(x.Item2)).Average(x => Convert.ToDouble(x.Item1)); } void Main() { var average_range = new List() {"10.1", "10.1", "0", "0"} ; var criteria_range = new List() {true, true, false, false }; Func criteria = c => c == true; AVERAGEIF(average_range, criteria_range, criteria).Dump(); }