我试图找出是否有办法为我的示例代码创建一个循环
// the objects below create a list of decimals
var ema12 = calc.ListCalculationData.Select(i => (double)i.Ema12);
var ema26 = calc.ListCalculationData.Select(i => (double)i.Ema26);
var ema = calc.ListCalculationData.Select(i => (double)i.Ema);
var adl = calc.ListCalculationData.Select(i => (double)i.ADL);
var r1 = GoodnessOfFit.RSquared(ema12);
var r2 = GoodnessOfFit.RSquared(ema26);
var r3 = GoodnessOfFit.RSquared(ema);
var r4 = GoodnessOfFit.RSquared(adl);
我正在尝试获得类似于以下伪代码的内容。请记住,每个var项都是小数列表
foreach (var item in calc.ListCalculationData.AsEnumerable())
{
var item2 = calc.ListCalculationData.Select(i => (double)item);
var r1 = GoodnessOfFit.RSquared(item2);
}
更多信息:
ListCalculationData是我在下面添加的自定义类的列表。我正在尝试做的是循环遍历该类中的每个变量并执行选择查询以在select查询返回的小数列表上执行拟合优度计算,这样可以简化我的代码并使其类似于my伪代码
public class CalculationData
{
public decimal Ema { get; set; }
public decimal Ema12 { get; set; }
public decimal Ema26 { get; set; }
public decimal ADL { get; set; }
}
更新:我尝试了本地功能,它失败了;预期和无效{
double r(Func<CalculationData, double> f) =>
{ GoodnessOfFit.RSquared(calc.ListCalculationData.Select(f), vectorArray) };
更新2:这是我现有的代码设置因为建议,但显然这不起作用,因为它说在这个上下文中我不存在名称:nameof(i.Ema12 )还因为我主要使用伪代码
MultipleRegressionInfo rn(Func<CalculationData, double> f, string name, int days)
{
MultipleRegressionInfo mrInfo = new MultipleRegressionInfo
{
RSquaredValue = GoodnessOfFit.RSquared(calc.ListCalculationData.Select(f), vectorArray),
ListValues = (List<double>)calc.ListCalculationData.Select(f).ToList(),
ValueName = name,
Days = days
};
listMRInfo.Add(mrInfo);
return mrInfo;
};
MultipleRegressionInfo rnList(Func<CalculationData, List<decimal>> f, string name, int days)
{
MultipleRegressionInfo mrInfo = new MultipleRegressionInfo
{
RSquaredValue = GoodnessOfFit.RSquared(calc.ListCalculationData.Select(f), vectorArray),
ListValues = (List<double>)calc.ListCalculationData.Select(f).ToList(),
ValueName = name,
Days = days
};
listMRInfo.Add(mrInfo);
return mrInfo;
};
foreach (CalculationData calc in ListCalculationData)
{
foreach (object value in calc)
{
if (value == typeof(decimal))
{
MultipleRegressionInfo r1 = rn(i => (double)i.value, nameof(i.value), 100)
}
else if (value == typeof(List<decimal>)
{
MultipleRegressionInfo r1 = rnList(i => i.value, nameof(i.value), 100)
}
}
}
答案 0 :(得分:1)
您可以将每个单独的字段表示为检索特定字段值的lambda(我认为这样更好),或者将字符串或PropertyType值表示为使用反射来实现相同的事物。
var getters = new Func<CalculationData, double>[] {
(i) => (double)i.Ema12,
(i) => (double)i.Ema26,
(i) => (double)i.Ema,
(i) => (double)i.ADL,
};
然后,只需获取每个IEnumerable<double>
序列并计算其RSquared值即可。
var dataseries = getters.Select((func) => calc.ListCalculationData.Select(func));
double[] results = dataseries.Select((data) => GoodnessOfFit.RSquared(data)).ToArray();
<小时/> 来自评论:
这与我正在寻找的类似,但我的课程中有40多个变量,我添加了更多信息,试图解释我尝试做什么,但我试图尝试防止额外的40行代码执行与您的代码类似的操作
以下内容应该使用反射进行您所要求的操作。
IEnumerable<Func<CalculationData, double>> getters =
typeof(CalculationData).GetProperties()
.Select<PropertyInfo, Func<CalculationData, double>>(
(PropertyInfo p) => (CalculationData x) => (double)(decimal)p.GetValue(x)
);
编辑:问题再次被编辑,我不再确定你需要间接的getter。请参阅https://dotnetfiddle.net/Sb65DZ,了解我如何编写此代码的准确示例。
答案 1 :(得分:0)
在Visual Studio 2015+中,您可以使用local functions(未经测试):
double r(Func<CalculationData, double> f) =>
GoodnessOfFit.RSquared(calc.ListCalculationData.Select(f));
double r1 = r(i => (double)i.Ema12), r2 = r(i => (double)i.Ema26),
r3 = r(i => (double)i.Ema) , r4 = r(i => (double)i.ADL);
或效率稍低的lambda:
Func<Func<CalculationData, double>, double> r = f =>
GoodnessOfFit.RSquared(calc.ListCalculationData.Select(f));
double r1 = r(i => (double)i.Ema12), r2 = r(i => (double)i.Ema26),
r3 = r(i => (double)i.Ema) , r4 = r(i => (double)i.ADL);
另一种选择可能是将它们转换为数组:
Func<CalculationData, double>[] lambdas = { i => (double)i.Ema12, i => (double)i.Ema26,
i => (double)i.Ema, i => (double)i.ADL };
double[] r = Array.ConvertAll(lambdas, f =>
GoodnessOfFit.RSquared(calc.ListCalculationData.Select(f)));
要使用反射查找具有max rsquared值的属性,您可以尝试:
Tuple<double, string> maxR = typeof(CalculationData).GetProperties().Max(p => Tuple.Create(
GoodnessOfFit.RSquared(calc.ListCalculationData.Select(i => Convert.ToDouble(p.GetValue(i)))), p.Name));
double maxRvalue = maxR.Item1;
string maxRname = maxR.Item2;
答案 2 :(得分:0)
您可以使用扩展方法一起收集常见的操作序列。
public static class CalculationDataExtensions
{
public static IEnumerable<double> CalcRSquared(
this IEnumerable<CalculationData> source,
Func<CalculationData, decimal> propertySelector)
{
IEnumerable<double> values = source
.Select(propertySelector)
.Select(x => (double)x);
return GoodnessOfFit.RSquared(values);
}
}
通过
调用var r1 = calc.ListCalculationData.CalcRSquared(x => x.Ema12);
var r2 = calc.ListCalculationData.CalcRSquared(x => x.Ema26);
var r3 = calc.ListCalculationData.CalcRSquared(x => x.Ema);
var r4 = calc.ListCalculationData.CalcRSquared(x => x.ADL);