c# - 带有 linq 的列表中的线性回归
问题描述
我有一个形成坡道系列的“步骤”列表。每个步骤都有一个start value
、一个end value
和一个duration
。这是一个示例图:
保证后续步骤的起始值等于结束值。它是一个单调的功能。
现在我需要在给定时间获取值。我已经有一个使用好的旧 foreach 的工作实现,但我想知道是否有一些聪明的方法可以使用linq
. 也许有人有替代该GetValueAt
功能的想法?
class Program
{
class Step
{
public double From { get; set; }
public double To { get; set; }
public int Duration { get; set; }
}
static void Main(string[] args)
{
var steps = new List<Step>
{
new Step { From = 0, To = 10, Duration = 20},
new Step { From = 10, To = 12, Duration = 10},
};
const double doubleTolerance = 0.001;
// test turning points
Debug.Assert(Math.Abs(GetValueAt(steps, 0) - 0) < doubleTolerance);
Debug.Assert(Math.Abs(GetValueAt(steps, 20) - 10) < doubleTolerance);
Debug.Assert(Math.Abs(GetValueAt(steps, 30) - 12) < doubleTolerance);
// test linear interpolation
Debug.Assert(Math.Abs(GetValueAt(steps, 10) - 5) < doubleTolerance);
Debug.Assert(Math.Abs(GetValueAt(steps, 25) - 11) < doubleTolerance);
}
static double GetValueAt(IList<Step> steps, int seconds)
{
// guard statements if seconds is within steps omitted here
var runningTime = steps.First().Duration;
var runningSeconds = seconds;
foreach (var step in steps)
{
if (seconds <= runningTime)
{
var x1 = 0; // stepStartTime
var x2 = step.Duration; // stepEndTime
var y1 = step.From; // stepStartValue
var y2 = step.To; // stepEndValue
var x = runningSeconds;
// linear interpolation
return y1 + (y2 - y1) / (x2 - x1) * (x - x1);
}
runningTime += step.Duration;
runningSeconds -= step.Duration;
}
return double.NaN;
}
}
解决方案
你可以试试Aggregate
:
static double GetValueAt(IList<Step> steps, int seconds)
{
var (value, remaining) = steps.Aggregate(
(Value: 0d, RemainingSeconds: seconds),
(secs, step) =>
{
if (secs.RemainingSeconds > step.Duration)
{
return (step.To, secs.RemainingSeconds - step.Duration);
}
else
{
return (secs.Value + ((step.To - step.From) / step.Duration) * secs.RemainingSeconds, 0);
}
});
return remaining > 0 ? double.NaN : value;
}
推荐阅读
- asp.net-core-2.0 - Asp.Net Core:如何正确地将数据从视图传递到控制器?
- javascript - 使用 JavaScript 的搜索栏中的词序
- node.js - 如何使用 Material-UI 创建 onSubmit
- apache-kafka - 如何将消息类型绑定到单个消费者组上的 Kafka 消费者?
- rabbitmq - 如果已经存在,RabbitMQ 是否创建队列/交换?
- spring-boot - 结合 oauth2+jwt 配置多个身份验证提供程序
- node.js - 在此示例中,如何使用 docker-compose 允许 2 个容器正确共享 .sock 文件?
- flutter - Flutter ButtonBar 儿童尺寸
- c# - 使用 svcutil 从 xsd 生成 DataContract 的问题
- python - 根据特定键合并字典列表