Получить индекс определенного элемента из списка, содержащего возможные дубликаты - PullRequest
1 голос
/ 10 июля 2011

хорошо, у меня есть список объектов класса, например:

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

Я хочу иметь возможность спросить список что-то вроде GetIndex ("orange", 2) и вернуть (в данном случае) индекс # для второго экземпляра рассматриваемого объекта (позиция 4).

Этот список будет динамически заполнен, и в нем даже может не быть оранжевого. Если это так, я хочу номер экземпляра второго параметра. Так что я могу получить второй апельсин или пятый манго и т. Д.

list.IndexOf (оранжевый) возвращает первый экземпляр любых дубликатов, поэтому мне нужно что-то еще.

Есть идеи?

PS: я не упомянул, что первым параметром будет строка!

Ответы [ 6 ]

3 голосов
/ 10 июля 2011
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;
}

Хотя довольно странно, что index начинается с 1, но результат начинается с 0.

2 голосов
/ 10 июля 2011

Вот общий поиск по расширению, который я только что написал:

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

Все, что вам нужно сделать, это назвать так:

int index = lst.GetIndex(apple, 2);

Если искомый предмет не найден, возвращается -1.

2 голосов
/ 10 июля 2011
        int index = lst.IndexOf(orange);
        if (index >= 0)
        {
            index = lst.IndexOf(orange, index + 1);
        }

или, чтобы сделать его обобщенным, вы можете использовать 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;
    }

Затем позвоните GetIndex(lst, orange, 2)

1 голос
/ 10 июля 2011

Вы можете расширить классы своим собственным методом для этого класса, к сожалению, это невозможно для универсальных классов, поэтому вместо этого вы даете тип с методом.

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);
1 голос
/ 10 июля 2011
var result = list.Select((x, i) => new { x, i })
                  .Where(t => t.x == fruit)
                  .Skip(k - 1)
                  .Select(t => t.i)
                  .First();
0 голосов
/ 10 июля 2011

Расширение ответа dtb на счет, когда вы не можете найти искомое значение:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...