C# 获得;“运行平均值”;名单
假设我有一张清单:C# 获得;“运行平均值”;名单,c#,list,C#,List,假设我有一张清单: List<int> numbers = new List<int>(); 列表编号=新列表(); 我试图得到它的“运行平均值”。(对不起,我真的不知道怎么称呼它) 例如: 此列表中的第一项是5,5的平均值是5,因此第一项平均值是5 此列表中的第二项是7,第五项和第七项的平均值是6,因此第二项的平均值是6 此列表中的第三项是10,5、7和10的平均值是7.3,因此第三项平均值是7.3 等等 这些第一平均值,第二平均值等就是我想要得到的平均值。我该怎么
List<int> numbers = new List<int>();
列表编号=新列表();
我试图得到它的“运行平均值”。(对不起,我真的不知道怎么称呼它)
例如:
此列表中的第一项是5
,5
的平均值是5
,因此第一项平均值是5
此列表中的第二项是7
,第五项和第七项的平均值是6
,因此第二项的平均值是6
此列表中的第三项是10
,5、7和10
的平均值是7.3
,因此第三项平均值是7.3
等等
这些第一平均值,第二平均值等就是我想要得到的平均值。我该怎么做呢?我一直在网上搜索,但老实说,我不太确定我应该找什么(您可以尝试以下方法:
var averages = Enumerable.Range(1, numbers.Count)
.Select(x => numbers.Take(x).Average())
.ToList();
List<double> FullList = GetRunningAverage(
new List<double>() { 100, 5, 5, 6, 23, 10, 56, 32, 54, 1, 3, 85, 65, 49, 22, 65, 32, 5, 2, 4, 5, 89, 110, 55, 6, 56, 57 },
3, // Looking back 3 items
3); // Looking forward 3 items
这将生成一个从1
到数字的序列。Count
。然后使用Take
每次将得到X
元素(您可以将X
视为索引,唯一的区别是它从1
开始,逐个增加到数字。Count
)从第一个元素开始,然后获取它们的平均值
。将它们放入列表。尝试以下操作:
string st = Console.ReadLine();
string[] strs = st.Split(' ');
List<int> numbers = new List<int>();
List<double> averages = new List<double>();
for (int i = 0; i < strs.Length; i++)
{
numbers.Add(int.Parse(strs[i]));
averages.Add(numbers.Average());
}
string st=控制台.ReadLine();
字符串[]strs=st.Split(“”);
列表编号=新列表();
列表平均值=新列表();
对于(int i=0;i
这将从标准输入中读取数字,数字在输入中用空格分隔。列表
List<int> numbers = new List<int>();
List<double> averages = new List<double>();
如果没有其他数据,比如元素数量、持续时间等,这样一个平均值列表本身通常意义不大
当移动平均值不是一对一的值时,此方法更适合。例如,应用程序存储值。然后定期(比如每分钟一次)计算并存储平均值。您需要的是“运行平均值”,而不是我假设的所有项目的一开始的平均值
运行平均值需要一个数字来告诉我们该向前看多远,一个数字来告诉我们该向前看多远
这将为您提供运行平均值:
public List<double> GetRunningAverage(List<double> SourceList, int ItemsBefore, int ItemsAfter)
{
List<double> TargetList = new List<double>() { };
// Only makes sense if the list is > 1 of course
if (SourceList.Count > 1)
{
for (int i = 0; i < SourceList.Count; i++)
{
int LookBack =
(ItemsBefore > i ? i : ItemsBefore);
int LookForward =
(ItemsAfter < SourceList.Count - i
? ItemsAfter : SourceList.Count - i);
TargetList.Add(SourceList.GetRange(i - LookBack, LookBack + LookForward).Average());
}
}
else
{
TargetList.AddRange(SourceList);
}
return TargetList;
}
public List GetRunningAverage(List SourceList,int ItemsBefore,int ItemsAfter)
{
List TargetList=new List(){};
//当然,只有当列表>1时才有意义
如果(SourceList.Count>1)
{
for(int i=0;ii?i:ItemsBefore);
国际展望=
(ItemsAfter
然后您可以这样使用它:
var averages = Enumerable.Range(1, numbers.Count)
.Select(x => numbers.Take(x).Average())
.ToList();
List<double> FullList = GetRunningAverage(
new List<double>() { 100, 5, 5, 6, 23, 10, 56, 32, 54, 1, 3, 85, 65, 49, 22, 65, 32, 5, 2, 4, 5, 89, 110, 55, 6, 56, 57 },
3, // Looking back 3 items
3); // Looking forward 3 items
List FullList=GetRunningAverage(
新列表{100,5,5,6,23,10,56,32,54,1,3,85,65,49,22,65,32,5,2,4,5,89,110,55,6,56,57},
3、//回顾3项
3) ;//期待3项
数字。平均值();
将为您提供列表中值的当前平均值。不清楚是否需要将其保存到新列表或what@Plutonix我想他想把它保存在一个新的列表中。新的列表
和for
循环就是你所需要的。这是一个非常简单的任务…你试过写代码吗?我已经编辑了你的标题。请我们看到,“,其中的共识是“不,他们不应该”。谢谢@JohnSaunders,我将记住这一点,以备将来参考。:)是的,这是一个非常巧妙的解决方案。谢谢这是一个优雅的解决方案,但有点低效,因为每次迭代都从头开始重新计算平均值。运行时将是O(n logn),而保持运行和的简单解决方案是O(n)@DaveM我也这么认为,对于这样的简单问题,不需要使用复杂的结构。@DaveM这是真的。如果速度和性能至关重要,则应优先选择其他方法。你的方法可能更适用于OP的技能水平。不太准确,看到他接受这个答案,我不这么认为。等等,你的答案不起作用!这不会得到“运行平均值”,而是将当前列表的平均值存储到平均值列表中,即这些值为7.3(根据OP)。当数字改变时,新的平均值也会改变。当列表中只有1个和2个值时,代码有义务调用它,这使塞尔曼先生的答案更好。(为什么averages
是一个可以添加到的列表)。