2014-01-25 48 views
3

我有两种方法,其中唯一的区别是一个拉姆达断言:通lambda作为参数

public static double LowerQuartile(this IOrderedEnumerable<double> list) 
{ 
    var median = list.Median(); 
    var elements = list.Where(x => x < median).ToList(); 
    if (!list.Contains(median)) 
     elements.Add(median); 

    return elements.OrderBy(x => x).Median(); 
} 

public static double UpperQuartile(this IOrderedEnumerable<double> list) 
{ 
    var median = list.Median(); 
    var elements = list.Where(x => x > median).ToList(); 
    if (!list.Contains(median)) 
     elements.Add(median); 

    return elements.OrderBy(x => x).Median(); 
} 

所以我想加入他们,并传递一个lambda作为参数。我试着用这样的东西:

public static double CalculateQuartile(IOrderedEnumerable<double> list, Expression<Func<IOrderedEnumerable<double>,bool>> predicate) 
{ 
    var median = list.Median(); 
    var elements = list.Where(predicate).ToList(); 
    if (!list.Contains(median)) 
     elements.Add(median); 

    return elements.OrderBy(x => x).Median(); 
} 

但它不起作用。我怎么能这样做?

回答

3

它可以是这样的

public static double Quartile(this IOrderedEnumerable<double> list, 
           Func<double,double,bool> predicate) 
{ 
    var median = list.Median(); 
    var elements = list.Where(x=>predicate(x,median)).ToList(); 
    if (!list.Contains(median)) 
     elements.Add(median); 

    return elements.OrderBy(x => x).Median(); 
} 

,你可以使用如

var val = list.Quartile((x, y) => x > y); 
2

拉姆达斯x => x < medianx => x > median都是Func<double, bool>类型。当你这样做有median作为内的另一个变量,你必须接受,作为一个参数,所以你最终会与Func<double, double, bool>

public static double CalculateQuartile(this IOrderedEnumerable<double> list, 
     Func<double, double, bool> predicate) 
{ … } 

可以做到这一点作为一个表达式,在粘贴在运行时参考median,但我会建议反对它。

相反,我会建议您以某种方式解决此问题,其中您的函数的用户不需要指定正确的lambda以使其工作。毕竟,你只有两种情况:上四分位数和下四分位数。所以,你可能只是想有一个布尔标志作为参数,而不是它允许你的上四分位下进行选择:

public static double CalculateQuartile(this IOrderedEnumerable<double> list, 
     bool calculateUpperQuartile = false) 
{ 
    var median = list.Median(); 
    var predicate = calculateUpperQuartile ? (x => x > median) : (x => x < median); 
    var elements = list.Where(predicate).ToList(); 
    if (!list.Contains(median)) 
     elements.Add(median); 

    return elements.OrderBy(x => x).Median(); 
} 

为了让用户更实用,我仍然会同时提供一个CalculateUpperQuartileCalculateLowerQuartile函数虽然 - 但当然,您可以在内部使用一个实现来处理两者。

+0

老实说,我会加入你和L.B.答案和我将保留CalculateUpperQuartile和CalculateLowerQuartile两种方法,但他们将使用第三种方法并通过谓词,这样最终用户仍有可能选择。 – kosnkov