tags:

views:

137

answers:

5

I'm trying to find a LINQ expression to compare two list elements.

What i want to do is:

List<int> _int = new List<int> { 1, 2, 3, 3, 4, 5};
_int.Where(x => x == _int[(_int.IndexOf(x)) + 1]);

Unfortunately, only the last +1 jumps out of the list's range.

How can I compare one item with its next in the list in a LINQ expression?

+2  A: 
int i = 0;
_int.Where(x => 
{
    i++;
    return i < _int.Length && x == _int[i];
});
Joel Coehoorn
Hasn't this the same issue with the last element?
inflagranti
Odrade
@Odrade, the original comment was before the check against the length was edited in.
Anthony Pegram
@Anthony. I see. Guess I should make it a habit to look at revisions.
Odrade
Thanks Joel, this version works fine.
Gpx
One more thing: you need to be a little careful with this code, as it creates a closure. Closures sometimes catch programmers by surprise later.
Joel Coehoorn
A: 

If you really want to do it with a lambda expression, add a bound check (that either always returns the last element or never, your choice).

An iterative approach would be more readable though, IMO.

inflagranti
A: 

It's an interesting problem, I would perhaps go for query expression syntax where it can be done like this

int[] array = {1,2,3,3,4,5};
var query = from item in array.Select((val, index) => new { val, index })
            join nextItem in array.Select((val, index) => new { val, index })
            on item.index equals (nextItem.index + 1)
            where item.val == nextItem.val
            select item.val;

Which would extract 3 from the array (or list). Of course, what can be done in query expression can obviously be done in lambda.

Edit Joel's solution is much simpler than mine and if you just need it to work on a List or an array, it is perfect. If you need something more flexible to work against any IEnumerable, then you would aim for something like the above (or something obviously better).

Anthony Pegram
+1  A: 
List<int> _int = new List<int> { 1, 2, 3, 3, 4, 5 };
Enumerable.Range(0, _int.Count - 1)
    .Select(i => new {val = _int[i], val2 = _int[i + 1]})
    .Where(check => check.val == check.val2)
    .Select(check => check.val);
Bill Barry
+2  A: 

Not that nice but should work.

list.Where((index, item) => index < list.Count - 1 && list[index + 1] == item)

Or the following.

list.Take(list.Count - 1).Where((index, item) => list[index + 1] == item)
Daniel Brückner
Something went wrong with "index, item" (i had to switch them) but your first solution works and there is no need for a counter outside!! Great, thanks.
Gpx