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