views:

69

answers:

3

Hi,

I've this Collection for example:

1: A

2: B

3: A

4: C

5: A

6: C

I want to get the second repeated item from this collection in a LINQ query,

the required result is: 3:A, 6:C

+2  A: 

A bit complicated but working:

int occ = 1; // 1 if you want the 2nd occurrence, 2 if you want the 3rd etc...
var nRepeatingElements = list.Select((x, idx) => new { Index = idx, Value = x })
                                .GroupBy(x => x.Value)
                                .Where(g => g.Count() > occ)
                                .Select(x => x.ElementAt(occ))
                                .ToList();

It returns a list with:

[Index:2 , Value: 'A']
[Index:5 , Value: 'C']

N.B.

The index is 1 lower than your desired solution, (because index is 0-based). But it's really easy to increment it, even in the first LINQ Select if you want:

Select((x, idx) => new { Index = idx+1, Value = x })
digEmAll
Thanks digEmAll, It's done :)
Homam
digEmAll, you forget about .Skip, .Take and implemented it on your own =)
vittore
A: 

just collection.Where( ... ).Skip(1).Take(1) should do

vittore
Mmh... I can't figure how you can use those LINQ expressions to get the solution. IMHO, you need to do something like a SQL expr "group by - having count" and AFAIK the only way to do that, is the one I posted...Could you post a complete and working solution ?
digEmAll
A: 
IEnumerable<Item> result =
  from item in items
  group item by item.Key into g
  let secondItem = g.Skip(1).Take(1) //.ToList()
  where secondItem.Any()
  select secondItem.First()

The ToList call is an optimization to prevent secondItem from being evaluated from g twice. It probably doesn't matter since we're only skipping 1, but it might matter if we start skipping 100.


Here's another solution using Where and a captured variable.

HashSet<Item.Key> seenIt = new HashSet<Item.Key>();
HashSet<Item.Key> returnedIt = new HashSet<Item.Key>();

IEnumerable<Item> result =
  items.Where(item => 
{
  key = Item.Key;
  if (!seenIt[key])
  {
    seenIt.Add(key);
  }
  else if (!returnedIt[key])
  {
    returnedIt.Add(key)
    return true;
  }
  return false;
});
David B