Reputation: 17
okay, I have a list of class objects like so:
List<fruit> lst = new List<fruit>();
lst.Add(orange);
lst.Add(apple);
lst.Add(grape);
lst.Add(grape);
lst.Add(orange);
lst.Add(pear);
lst.Add(apple);
I want to be able to ask the list something like GetIndex("orange", 2) and have it return (in this case) the index # for the second instance of object in question (position 4).
This list will be dynamically filled, and it may not even have an orange to begin with. If it does, I want the instance number of the second parameter. So I can get the second orange, or get fifth mango, etc.
list.IndexOf(orange) returns the first instance of any duplicates, so I need something else.
Any ideas?
PS: I failed to mention that the first param will be a string!
Upvotes: 1
Views: 10379
Reputation: 18345
An extension of dtb's answer to account for when you don't find the value you're looking for:
public int GetIndex<T>(IEnumerable<T> list, T item, int itemNum) {
// result is a nullable int containing the index
var result = list.Select((x, i) => new { x, i })
.Where(t => item.Equals(t.x))
.Skip(itemNum - 1)
.Select(t => (int?)t.i)
.FirstOrDefault();
// return -1 when item was not found
return (result.HasValue ? result.Value : -1);
}
Upvotes: 0
Reputation: 93050
int index = lst.IndexOf(orange);
if (index >= 0)
{
index = lst.IndexOf(orange, index + 1);
}
or to make it generic you can use some LINQ:
static int GetIndex(IEnumerable<Fruit> li, Fruit ob, int k)
{
var tmp = li.Select((it, i) => new Tuple<int, Fruit>(i, it)).Where(tup => tup.Item2 == ob).Skip(k - 1).FirstOrDefault();
if (tmp == null)
return -1;
else
return tmp.Item1;
}
Then call GetIndex(lst, orange, 2)
Upvotes: 2
Reputation: 13517
Here's a generic extension search I just wrote up:
public static class ListExtension
{
public static int GetIndex<T>(this List<T> entity, T what, int find)
{
int found = 0;
int index = -1;
while ((index = entity.IndexOf(what, (index + 1))) != -1)
{
found++;
if (found == find)
break;
}
return (index);
}
}
All you have to do is call it like so:
int index = lst.GetIndex(apple, 2);
If the item you are looking for isn't found, it returns -1.
Upvotes: 2
Reputation: 5126
You can extend classes with your own method for that class, sadly this is not possible for generic classes, so instead you give the type with the method.
public static class ListExtension
{
public static int GetIndex<T>(this List<T> list, T value, int skipMatches = 1)
{
for (int i = 0; i < list.Count; i++)
if (list[i].Equals(value))
{
skipMatches--;
if (skipMatches == 0)
return i;
}
return -1;
}
}
List<int> list = new List<int>();
list.Add(3);
list.Add(4);
list.Add(5);
list.Add(4);
int secondFour = (int)list.GetIndex(4, 2);
Upvotes: 1
Reputation: 244928
public static int GetIndex<T>(this IEnumerable<T> lst, T obj, int index)
{
return lst.Select((o, i) => new { o, i })
.Where(x => x.o.Equals(obj))
.ElementAt(index - 1)
.i;
}
Although it's kind of strange that index
starts at 1, but the result starts at 0.
Upvotes: 3
Reputation: 217341
var result = list.Select((x, i) => new { x, i })
.Where(t => t.x == fruit)
.Skip(k - 1)
.Select(t => t.i)
.First();
Upvotes: 1