2011-05-11 15 views
6

私は次のコードラムダ式

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

    return result.ToList(); 
} 

を持っていると私はconditionの正しい種類は何GetIndices(someList, (p, index) => (someList[index].Height < someList[index - 1].Height))

のようにそれを呼び出すしたいと思いますか?

答えて

0

お試しFunc<bool>

正確な量の入力パラメータを使用してa variantを入力します。

1
Func<T, bool> 

は、トリックを行う必要がありますが、あなたは(あなたがWhere句で条件を使用する場合)あなたは、インデックスを渡すことはできませんのでごラムダビットを変更する必要があるとしています。あなたが簡単にあなたのラムダを変更することができます:あなたはそれを読む方法を学ぶたら、将来の参考のために

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

、拡張メソッドのためのMSDNドキュメントは、(その部分が少しかかります)素晴らしいです:

MSDN - Enumerable.Where Method

これは拡張メソッドなので、最初のパラメータ(IEnumerable<TSource>)は、メソッドを呼び出すコレクション(ケースではList<T>)です。

2番目のパラメータは、一致する必要があるパラメータです。ドキュメントはFunc<TSource, bool>のために呼び出し、TSourceはあなたのケースでTあるので...あなたはFunc<T, bool>

+0

これは 'someList'が大きい場合は、ここでのパフォーマンス上の問題を導入している可能性があることを小さな警告で、動作するはずは – jeroenh

4

を取得し、あなたのコード内のエラーがあります:Wherebool値を返し、入力として、リストの要素の型を持つデリゲートを期待しています。

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

ですから、あなたがjeroenhが実現同様

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

も' Enumerable.Where'方法( 'IndexOf'はO(N)操作です) Func を受け付けるオーバーロードがあります。 – Tesserex

+0

@テッセレックス:しかし、あなたは元のインデックスを失う、私は思うよ – jeroenh

1

としてGetIndicesの実装を書き換えるしなければならないことを意味、私はあなたがFunc<T,int,bool>をしたいと思うあなたのスペックから、しかし、あなたをFunc<int,bool>

が必要になります元のインデックスを取得する必要があります。 Funct<T,int,bool>の条件は、クエリで作成された匿名型ではなく、アイテムとそのインデックスを認識する必要があるため、条件が少し変わります。また、インデックス== 0であるため、先行する項目(index-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

+0

はい、LINQを使っていても、もっと簡単に行うことができます。 'Where()'を最初に使うと、 'Func 'を受け取り、そのインデックスを渡します。 'for'ループ、および' Func <> '条件の間違いは、引き続き渡して使用することができます。 –