2014-01-25 47 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