2011-05-11 155 views
6

我有以下代碼Lambda表達式作爲函數參數

List<int> GetIndices<T>(List<T> list, ?????? condition 
{ 
    var result = 
      list 
       .Select((p, index) => index) 
       .Where(condition); 

    return result.ToList(); 
} 

而且我想這樣稱呼它GetIndices(someList, (p, index) => (someList[index].Height < someList[index - 1].Height))

什麼是正確的類型condition

回答

1
Func<T, bool> 

應該做的伎倆,但你將不得不修改您的拉姆達一點,因爲你無法通過索引(如果你想Where子句中使用的條件)。你可以很容易地改變你的lambda來:

p => someList[someList.IndexOf(p).Height < someList[someList.IndexOf(p)-1].Height 

以供將來參考,爲擴展方法的MSDN文檔是偉大的,一旦你學會如何閱讀(這部分需要多一點):

MSDN - Enumerable.Where Method

由於這是一種擴展方法,因此第一個參數(IEnumerable<TSource>)就是您要調用該方法的集合(在您的案例中爲List<T>)。

第二個參數是你需要匹配的。由於文件要求Func<TSource, bool>TSource你的情況T ...你Func<T, bool>

+0

這應該工作,與小警告,如果'someList'大你可能已經在這裏推出了性能問題('IndexOf'是O(N)操作) – jeroenh 2011-05-11 15:04:46

4

有在你的代碼中的錯誤:Where預計返回bool值並具有列表元素類型作爲輸入的委託。

var result = list 
    .Select((p, index) => index) // projects the element to it's index (of type int) 
    .Where(condition);   // => expects Func<int, bool> 

所以你需要Func<int,bool>

不過,從你的天賦我想你想Func<T,int,bool>,這意味着你必須重寫你的GetIndices執行情況

var result = list 
    .Select((p, index) => new {p, index}) 
    .Where(x => condition(x.p, x.index)) 
    .Select(x => x.index); 
+0

的'Enumerable.Where'方法還有一個接受Func 的重載。 – Tesserex 2011-05-11 14:47:30

+0

@Tesserex:但是你鬆了原來的索引,我認爲 – jeroenh 2011-05-11 14:52:59

1

像jeroenh實現,你需要捕獲原始索引。您傳遞的Funct<T,int,bool>條件只需要知道該項目及其索引,而不是在查詢中創建的匿名類型,因此傳遞的條件會發生一些變化。它也應該處理索引== 0並因此沒有前面項目(索引-1)的情況。

class Program { 
    static void Main(string[] args) { 
     var items = Item.GetItems(); 
     // mind the case where index == 0 so you don't grab an item out of bounds 
     var ind = GetIndices(items, 
      (p, index) => (h.index == 0) ? false : p.Height < items[ index - 1 ].Height); 
    } 

    static List<int> GetIndices<T>(List<T> list, Func<T, int, bool> condition) { 
     var res = list 
      .Select((item, index) => new { item, index }) // capture original index 
      .Where(h => condition(h.item, h.index)) 
      .Select(h => h.index); // reduce to the index again 
     return res.ToList(); 
    } 
} 

class Item { 
    public int Height { 
     get; 
     set; 
    } 
    public Item(int h) { 
     Height = h; 
    } 
    static public List<Item> GetItems() { 
     return new List<Item>(new[]{ 
        new Item(1), 
        new Item(4), 
        new Item(2), 
        new Item(5) 
     }); 
    } 
} 
+0

它看起來過於複雜。我最好不要使用LINQ? – kasperhj 2011-05-12 14:39:16

+0

是的,它可以做得更簡單,甚至可以使用LINQ。如果首先使用'Where()',它將接受'Func '並傳遞索引。 'for'循環也沒有錯,並且'Func <>'條件仍然可以被傳遞和使用。 – 2011-05-13 01:42:49

相關問題