Lambda expression as function parameter
I have the following code
List<int> GetIndices<T>(Lis开发者_Go百科t<T> list, ?????? condition
{
var result =
list
.Select((p, index) => index)
.Where(condition);
return result.ToList();
}
And I would like to call it like GetIndices(someList, (p, index) => (someList[index].Height < someList[index - 1].Height))
What is the correct type of condition
?
There's an error in your code: Where
expects a delegate that returns a bool
value and has the list element type as input.
var result = list
.Select((p, index) => index) // projects the element to it's index (of type int)
.Where(condition); // => expects Func<int, bool>
So you would need Func<int,bool>
However, from your spec I think you want Func<T,int,bool>
, which means you have to rewrite your implementation of GetIndices
as
var result = list
.Select((p, index) => new {p, index})
.Where(x => condition(x.p, x.index))
.Select(x => x.index);
Func<T, bool>
Should do the trick but you're going to have to modify your lambda a bit because you can't pass the index (if you want to use condition in the Where
clause). You could easily change your lambda to:
p => someList[someList.IndexOf(p).Height < someList[someList.IndexOf(p)-1].Height
For future reference, the MSDN documentation for the extension methods is great once you learn how to read it (that part takes a bit):
MSDN - Enumerable.Where Method
Since this is an extension method, the first parameter (IEnumerable<TSource>
) is the collection you're calling the method on (List<T>
in your case).
The second parameter is what you need to match. Since the documentation calls for Func<TSource, bool>
and TSource
is T
in your case...you get Func<T, bool>
Like jeroenh realized, you need to capture the original index. The Funct<T,int,bool>
condition you pass only needs to be aware of the item and its index, not the anonymous type created in the query, so the condition passed changes a bit. It also should handle the situation where the index == 0 and therefore there are no preceding items (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)
} );
}
}
Try Func<bool>
.
Or rather a variant with the correct amount of input parameters.
精彩评论