tags:

views:

151

answers:

3

Taking a look at my question HERE, I now want to return the next recommendation object (after) the one that matches the criteria.

So say I found item 6 out of 10, I'd like the query to return item 7 instead.

Or is there a better way?

+2  A: 

Since you have a List<T> object you can use its FindIndex method instead of Where to get the index of the first matching item rather than the item itself:

    int index = recommendations.FindIndex(rp =>
        rp.Products.Any(p => p.Product.Code == "A") && rp.Products.Any(p => p.Product.Code == "B"))

Once you have the index you can get the next item or previous item or whatever you want.

Evgeny
+1 Yeah I think this will work fine.
griegs
A: 

Is item 7 a match to your Where clause? If so, use the Skip() and Take() extension methods:

var myProducts =
   from rp in recommendations
   where
      cp.Products.Any(p => p.Product.Code == "A") &&
      cp.Products.Any(p => p.Product.Code == "B")
   select rp;

var nextProduct = myProducts.Skip(1).Take(1);
spoulson
I dont think this will exactly work. In the OPs case it would seem that the original would only return 1 result, and they want the next in the ORIGINAL list.
astander
@spoulson, that's correct. I want to find the matching item and then return the next item in the list.
griegs
A: 

This should do it. I haven't constructed a test for it specifically.

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    on item1.Index equals item2.Index - 1
                    where item1.Rec.Products.Any(p => p.Code == "A")
                    && item1.Rec.Products.Any(p => p.Code == "B")
                    select item2.Rec;

If you needed both records, the select statement could be

select new { MatchingItem = item1.Rec, NextItem = item2.Rec };

But then you would have to do a grouping to account for a matching item being the last item in the list (there would not be a next item in that case).

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    on item1.Index equals item2.Index - 1
                    into groupjoin
                    from i2 in groupjoin.DefaultIfEmpty ()
                    where item1.Rec.Products.Any(p => p.Code == "A")
                    && item1.Rec.Products.Any(p => p.Code == "B")
                    select new { MatchingItem = item1.Rec, NextItem = i2 == null ? null : i2.Rec };

The code I did test was something similar with a list of strings.

List<string> list = new List<string>() { "a", "b", "c", "a", "d", "a", "e" };

var query = from item1 in list.Select((s, idx) => new { Item = s, Index = idx })
            join item2 in list.Select((s, idx) => new { Item = s, Index = idx })
            on item1.Index equals item2.Index - 1
            where item1.Item == "a"
            select item2.Item;

Which returns b, d, and e.

Anthony Pegram