score:2

Accepted answer

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

score:1

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

Related Articles