2016-03-05 52 views
3

我有一個簡單的目標:通行證聚合函數作爲參數

public class Machine 
{ 
    public string Name { get; set; } 

    public int Power { get; set; } 

    public int Type { get; set; } 
} 

再有就是持有這些對象的List類:

public class Aggregations 
{ 
    private List<Machine> _machines; 

    public Aggregations() 
    { 
     _machines = new List<Machine> 
      { 
       new Machine { Name = "XLR1", Power = 111, Type = 1 }, 
       new Machine { Name = "XLR2", Power = 222, Type = 1 }, 
       new Machine { Name = "XLR3", Power = 333, Type = 1 }, 
       new Machine { Name = "XLR4", Power = 444, Type = 1 }, 
       new Machine { Name = "XLR5", Power = 555, Type = 2 }, 
       new Machine { Name = "XLR6", Power = 666, Type = 2 } 
      };   
    } 
// ... 
} 

有是兩個函數返回的機器列表具體標準如下:

public IEnumerable<Machine> MaxPower(IEnumerable<Machine> machines) 
    { 
     var maxPowerMachinesPerType = new List<Machine>(); 

     var groups = machines.GroupBy(m => m.Type); 
     foreach (var g in groups) 
     { 
      var max = g.Max(m => m.Power); 
      var machine = g.First(m => m.Power == max); 
      maxPowerMachinesPerType.Add(machine); 
     } 

     return maxPowerMachinesPerType; 
    } 


    public IEnumerable<Machine> MinPower(IEnumerable<Machine> machines) 
    { 
     var minPowerMachinesPerType = new List<Machine>(); 

     var groups = machines.GroupBy(m => m.Type); 
     foreach (var g in groups) 
     { 
      var min = g.Min(m => m.Power); 
      var machine = g.First(m => m.Power == min); 
      minPowerMachinesPerType.Add(machine); 
     } 

     return minPowerMachinesPerType; 
    } 
} 

正如您所看到的,兩個函數幾乎相等。只有「最大」和「最小」不同。

這些函數被稱爲是這樣的:

IEnumerable<Machine> maxPowerMachines = MaxPower(_machines); 
IEnumerable<Machine> minPowerMachines = MinPower(_machines); 

因爲我實際的程序稍微複雜一些,我雖然想調用其他聚合函數,我想通過聚合函數用作一個參數:(僞代碼)

IEnumerable<Machine> maxPowerMachines = SuperFunction(_machines, m => m.Max); 
IEnumerable<Machine> minPowerMachines = SuperFunction(_machines, m => m.Min); 
IEnumerable<Machine> averagePowerMachines = SuperFunction(_machines, m => m.Average); 

我希望你有意向。

回答

3

由於MinMax具有相同的簽名,即它們都採取IEnumerable<T>和產生T,你可以做這樣的:

public IEnumerable<Machine> SelectPower(
    IEnumerable<Machine> machines 
, Func<IEnumerable<int>,int> powerSelector 
) { 
    var res = new List<Machine>(); 
    var groups = machines.GroupBy(m => m.Type); 
    foreach (var g in groups) { 
     var targetPower = powerSelector(g.Select(m => m.Power)); 
     var machine = g.First(m => m.Power == targetPower); 
     res.Add(machine); 
    } 
    return res; 
} 

現在你可以打電話給你的方法是這樣的:

IEnumerable<Machine> maxPowerMachines = SuperFunction(_machines, m => m.Max()); 
IEnumerable<Machine> minPowerMachines = SuperFunction(_machines, m => m.Min()); 
+0

正是我在找的東西。我嘗試過這樣的事情,但是缺少'g.Select(m => m.Power)'部分。謝謝! – RamNow

0

Func<T>聽起來像你在找什麼。主導類型<T>顯示輸入,最後<T>顯示的返回值,所以你要尋找的是這樣的:

Func<IEnumerable<Machine>, IEnumerable<Machine>> aggregateFunction = MaxPower; 


    //Now you can pass aggregateFunction around as a variable. You can call it like so: 

    var machines = Aggregations(); 

    aggregateFunction.Invoke(machines);