C# 寻找使用矩阵先前值的Matlab矩阵运算的等效LINQ查询
我想使用LINQ简化C#中列表的生成。我的目标是使用另一个列表的值用操作填充新列表。 我愿意使用第三方库,如Deedle或MathNet,如果它们能够重现与我当前解决方案类似的性能 在Matlab中实现目标的等效方法是使用简单的矩阵运算和点运算,如以下代码所示:C# 寻找使用矩阵先前值的Matlab矩阵运算的等效LINQ查询,c#,linq,C#,Linq,我想使用LINQ简化C#中列表的生成。我的目标是使用另一个列表的值用操作填充新列表。 我愿意使用第三方库,如Deedle或MathNet,如果它们能够重现与我当前解决方案类似的性能 在Matlab中实现目标的等效方法是使用简单的矩阵运算和点运算,如以下代码所示: dailryletlist=(dailcloselist(2:end)-dailcloselist(1:end-1))。/dailcloselist(1:end-1) 它创建一个新数组,迭代dailcloselist,并为每个元素从da
dailryletlist=(dailcloselist(2:end)-dailcloselist(1:end-1))。/dailcloselist(1:end-1)
它创建一个新数组,迭代dailcloselist
,并为每个元素从dailcloselist[i]
中减去dailcloselist[i-1]
,然后将结果除以dailcloselist[i-1]
,最后将值推送到新创建的数组中
我目前解决这个问题的办法是:
var dailyCloseList = new List<double>{11.8d, 11.7d, 13d, 12.6d, 15d};
var dailyRetList = new List<double>();
for (var i = 1; i < dailyCloseList.Count; i++)
{
dailyRetList.Add((dailyCloseList[i] - dailyCloseList[i-1])/dailyCloseList[i-1]);
}
var dailyCloseList=新列表{11.8d、11.7d、13d、12.6d、15d};
var dailryretlist=新列表();
对于(变量i=1;i
您可以在Linq中使用此选项:
var m = Enumerable.Range(1, dailyCloseList.Count - 1)
.Select(i => (dailyCloseList[i] - dailyCloseList[i - 1])/ dailyCloseList[i - 1])
.ToList();
检查是否存在除零异常总是有帮助的。您可以在Linq中使用此选项:
var m = Enumerable.Range(1, dailyCloseList.Count - 1)
.Select(i => (dailyCloseList[i] - dailyCloseList[i - 1])/ dailyCloseList[i - 1])
.ToList();
检查是否有被零除的异常总是有帮助的。另一个选项是使用
Zip
:
var change = dailyCloseList.Zip(dailyCloseList.Skip(1))
.Select((x,y) => (y - x)/x)
.ToList();
另一种选择是使用
Zip
:
var change = dailyCloseList.Zip(dailyCloseList.Skip(1))
.Select((x,y) => (y - x)/x)
.ToList();
我认为最关键的方法就是这样
var dailyRetList = dailyCloseList
.ConsecutivePairs((a, b) => (b - a) / a)
.ToList();
当然,您必须定义连续对
函数(在某个地方定义一次)。但与Guaravsa解决方案不同的是,它适用于IEnumerable
,因此不需要直接索引访问。但这一切都是有代价的。原始的简单循环比任何使用枚举的解决方案快3倍左右(顺便说一句,您应该在开始时预先分配列表以获得最佳性能)
以及功能实现,仅为了完整性:
public static IEnumerable<Q> ConsecutivePairs<T, Q>(this IEnumerable<T> sequence, Func<T, T, Q> selector)
{
using(var en = sequence.GetEnumerator())
{
if (!en.MoveNext()) { yield break; }
T prev = en.Current;
while (en.MoveNext())
{
yield return selector(prev, en.Current);
prev = en.Current;
}
}
}
公共静态IEnumerable连续对(此IEnumerable序列,Func选择器)
{
使用(var en=sequence.GetEnumerator())
{
如果(!en.MoveNext()){yield break;}
T上一次=正常电流;
while(en.MoveNext())
{
收益率返回选择器(上一个,当前的);
上一次=正常电流;
}
}
}
我认为最关键的方法是
var dailyRetList = dailyCloseList
.ConsecutivePairs((a, b) => (b - a) / a)
.ToList();
当然,您必须定义连续对
函数(在某个地方定义一次)。但与Guaravsa解决方案不同的是,它适用于IEnumerable
,因此不需要直接索引访问。但这一切都是有代价的。原始的简单循环比任何使用枚举的解决方案快3倍左右(顺便说一句,您应该在开始时预先分配列表以获得最佳性能)
以及功能实现,仅为了完整性:
public static IEnumerable<Q> ConsecutivePairs<T, Q>(this IEnumerable<T> sequence, Func<T, T, Q> selector)
{
using(var en = sequence.GetEnumerator())
{
if (!en.MoveNext()) { yield break; }
T prev = en.Current;
while (en.MoveNext())
{
yield return selector(prev, en.Current);
prev = en.Current;
}
}
}
公共静态IEnumerable连续对(此IEnumerable序列,Func选择器)
{
使用(var en=sequence.GetEnumerator())
{
如果(!en.MoveNext()){yield break;}
T上一次=正常电流;
while(en.MoveNext())
{
收益率返回选择器(上一个,当前的);
上一次=正常电流;
}
}
}
欢迎来到SO,您能否提供有关预期结果的更多详细信息,因为不清楚dailyRetList=(dailyCloseList(2:end)-dailyCloseList(1:end-1))。/dailyCloseList(1:end-1)
有什么作用。您当前的解决方案似乎很好。它有什么问题吗,或者你只是想在更少的代码中获得同样的结果?@Ben是的,我的解决方案很有效,但我只是从C#和LINQ开始,所以我只是想看看是否有办法编写更少的代码。我不确定。你可以试试这个,但我怀疑你现在做的其实很简单。为什么你想写更少的代码?欢迎这么做,你能提供你的问题更多关于你预期结果的细节吗,因为不清楚什么是dailRetList=(dailyCloseList(2:end)-dailyCloseList(1:end-1))。/dailyCloseList(1:end-1)
可以。您当前的解决方案似乎很好。它有什么问题吗,或者你只是想在更少的代码中获得同样的结果?@Ben是的,我的解决方案很有效,但我只是从C#和LINQ开始,所以我只是想看看是否有办法编写更少的代码。我不确定。你可以试试这个,但我怀疑你现在做的其实很简单。为什么你想写更少的代码?