6

I have the following code

List<int> GetIndices<T>(List<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?

4 Answers 4

4

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);  
Sign up to request clarification or add additional context in comments.

2 Comments

The Enumerable.Where method also has an overload accepting a Func<T, int, bool>.
@Tesserex: but then you loose the original index, I think
1
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>

1 Comment

this should work, with the small caveat that if someList is large you might have introduced a performance problem here (IndexOf is an O(N) operation)
1

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)
        } );
    }
}

2 Comments

It looks overly complicated. I might be better off not using linq?
Yes, it could be done simpler, maybe even with LINQ. If you use Where() first, it will accept a Func<T,int,bool> and pass the index. Nothing wrong with a for loop, either, and the Func<> condition can still be passed and used.
0

Try Func<bool>.

Or rather a variant with the correct amount of input parameters.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.