Я написал это:
public static class EnumerableExtensions
{
public static int IndexOf<T>(this IEnumerable<T> obj, T value)
{
return obj
.Select((a, i) => (a.Equals(value)) ? i : -1)
.Max();
}
public static int IndexOf<T>(this IEnumerable<T> obj, T value
, IEqualityComparer<T> comparer)
{
return obj
.Select((a, i) => (comparer.Equals(a, value)) ? i : -1)
.Max();
}
}
Но я не знаю, существует ли он уже, не так ли?
Max
подходом состоит в том, что a: он продолжает искать, а b: он возвращает последний индекс, когда есть дубликаты (люди обычно ожидают первый индекс)ToList()/FindIndex()
трюк работает лучшеОтветы:
Весь смысл IEnumerable заключается в том, что вы можете лениво перебирать содержимое. Таким образом, на самом деле нет понятия индекса. То, что вы делаете, на самом деле не имеет большого смысла для IEnumerable. Если вам нужно что-то, что поддерживает доступ по индексу, поместите это в фактический список или коллекцию.
источник
IEnumerable<>
. Я не покупаю всю догму "ты должен делать это".IEnumerable
тоEnumerable.ElementAt
не существовало бы.IndexOf
является просто обратным - любой аргумент против него должен применяться в равной степени кElementAt
.Я бы поставил под сомнение мудрость, но, возможно,
(используется
EqualityComparer<T>.Default
для эмуляции,!=
если необходимо) - но вам нужно смотреть, чтобы вернуть -1, если не найден ... так что, возможно, просто сделать это долгий путьисточник
TakeWhile
умный! Имейте в виду, что это возвращает,Count
если элемент не существует, что является отклонением от стандартного поведения.Я бы реализовал это так:
источник
==
Может понадобиться работать?KVP<T, int?>
(обнуляемый индекс)IList<T>
и, если да, отложить его метод IndexOf на тот случай, если он имеет оптимизацию для конкретного типа.То, как я сейчас это делаю, немного короче, чем уже предлагалось, и, насколько я могу судить, дает желаемый результат:
Это немного неуклюже, но это делает работу и довольно кратко.
источник
Лучший способ поймать позицию -
FindIndex
эта функция доступна только дляList<>
пример
Если у вас есть перечислитель или массив, используйте этот способ
или
источник
Я думаю, что лучший вариант - это реализовать так:
Это также не будет создавать анонимный объект
источник
Я немного опоздал в игре, я знаю ... но это то, что я недавно сделал. Он немного отличается от вашего, но позволяет программисту определять, какой должна быть операция равенства (предикат). Который я считаю очень полезным при работе с различными типами, так как тогда у меня есть общий способ сделать это независимо от типа объекта и
<T>
встроенного оператора равенства.Он также имеет очень маленький объем памяти и очень, очень быстрый / эффективный ... если вы заботитесь об этом.
В худшем случае вы просто добавите это в свой список расширений.
Во всяком случае ... вот оно.
Надеюсь, это кому-нибудь поможет.
источник
GetEnumerator
и ,MoveNext
а не простоforeach
?foreach
вызоветDispose
перечислитель, если он реализуетIDisposable
. (См. Stackoverflow.com/questions/4982396/… ) Поскольку код в этом ответе не знает, является ли результат вызоваGetEnumerator
одноразовым или нет, он должен сделать то же самое. В тот момент мне все еще неясно, есть ли в этом перфекционная выгода, хотя был какой-то дополнительный ИЛ, цель которого не прыгнула на меня!foreach
циклом, и в этом случае для конкретного случаяT
будучи типом значения, он может сохранять операции box / unbox с помощью цикла while. Однако это не подтверждается IL, который я получил по версии вашего ответаforeach
. Я все же считаю, что условное удаление итератора важно. Не могли бы вы изменить ответ, чтобы включить это?Несколько лет спустя, но он использует Linq, возвращает -1, если не найден, не создает дополнительных объектов и должен закорачиваться при обнаружении [в отличие от итерации по всему IEnumerable]:
Где «FirstOr» это:
источник
source.Where
и другоеsource.DefaultIfEmpty
, например, создастIEnumerable
друг.Наткнулся сегодня на поиск ответов, и я подумал, что добавлю свою версию в список (без каламбура). Он содержит нулевой условный оператор c # 6.0
Я провел несколько «гонок на старых лошадях» (тестирование) и для больших коллекций (~ 100 000), в худшем случае, в конце концов, предмет, который вы хотите получить, это в 2 раза быстрее, чем вы
ToList().FindIndex()
. Если нужный предмет находится посередине, он примерно в 4 раза быстрее.Для небольших коллекций (~ 10000) это кажется лишь незначительно быстрее
Вот как я это проверял https://gist.github.com/insulind/16310945247fcf13ba186a45734f254e
источник
Используя ответ @Marc Gravell, я нашел способ использовать следующий метод:
чтобы получить -1, когда предмет не может быть найден:
Я думаю, что этот путь может быть как самым быстрым, так и простым. Тем не менее, я еще не тестировал выступления.
источник
Альтернативой нахождению индекса после факта является обертка Enumerable, чем-то похожая на использование метода Linq GroupBy ().
Что дает вариант использования:
источник
Это может быть действительно круто с расширением (функционирующим как прокси), например:
Который автоматически назначит индексы коллекции, доступной через это
Index
свойство.Интерфейс:
Пользовательское расширение (вероятно, наиболее полезное для работы с EF и DbContext):
источник