我写这样的:

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

但我不知道,如果它已经存在,不是吗?

有帮助吗?

解决方案

把事情做出来为IEnumerable是这样你就可以懒洋洋地遍历内容的全部意义。因此,不存在的确实的索引的概念。你在做什么真的没有很大的意义的一个IEnumerable。如果你需要的东西,通过索引支持接入,把它放在一个实际的列表或集合。

其他提示

我要质疑的智慧,但也许是:

source.TakeWhile(x => x != value).Count();

(使用EqualityComparer<T>.Default如果需要效仿!=) - 但你需要注意返回-1,如果没有找到,所以也许只是做了很长的路。

public static int IndexOf<T>(this IEnumerable<T> source, T value)
{
    int index = 0;
    var comparer = EqualityComparer<T>.Default; // or pass in as a parameter
    foreach (T item in source)
    {
        if (comparer.Equals(item, value)) return index;
        index++;
    }
    return -1;
}

我将执行这样的:

public static class EnumerableExtensions
{
    public static int IndexOf<T>(this IEnumerable<T> obj, T value)
    {
        return obj.IndexOf(value, null);
    }

    public static int IndexOf<T>(this IEnumerable<T> obj, T value, IEqualityComparer<T> comparer)
    {
        comparer = comparer ?? EqualityComparer<T>.Default;
        var found = obj
            .Select((a, i) => new { a, i })
            .FirstOrDefault(x => comparer.Equals(x.a, value));
        return found == null ? -1 : found.i;
    }
}

目前,我这样做的方式是不是已经建议那些短一点,据我可以告诉给了期望的结果:

 var index = haystack.ToList().IndexOf(needle);

这是一个有点笨拙,但它的工作,是相当简洁。

我认为最好的办法是实行这样的:

public static int IndexOf<T>(this IEnumerable<T> enumerable, T element, IEqualityComparer<T> comparer = null)
{
    int i = 0;
    comparer = comparer ?? EqualityComparer<T>.Default;
    foreach (var currentElement in enumerable)
    {
        if (comparer.Equals(currentElement, element))
        {
            return i;
        }

        i++;
    }

    return -1;
}

它也不会产生匿名对象

捉位置的最佳方法是通过FindIndex此功能仅适用于List<>

实施例

int id = listMyObject.FindIndex(x => x.Id == 15); 

如果你有枚举或阵列用这种方式

int id = myEnumerator.ToList().FindIndex(x => x.Id == 15); 

 int id = myArray.ToList().FindIndex(x => x.Id == 15); 

一个位在游戏后期,我知道......不过这是我最近做了。它比你的略有不同,但允许程序员决定什么平等的操作需要为(谓语)。我觉得这是非常有用的不同类型的处理时,因为我那么不管有没有做这件事的对象类型和<T>建在平等运营商的通用方法。

它也有一个非常非常小的内存占用,是非常,非常快/高效的...如果你关心这个。

目前糟糕的是,你只添加到您的扩展名列表。

总之......在这里。

 public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate)
 {
     int retval = -1;
     var enumerator = source.GetEnumerator();

     while (enumerator.MoveNext())
     {
         retval += 1;
         if (predicate(enumerator.Current))
         {
             IDisposable disposable = enumerator as System.IDisposable;
             if (disposable != null) disposable.Dispose();
             return retval;
         }
     }
     IDisposable disposable = enumerator as System.IDisposable;
     if (disposable != null) disposable.Dispose();
     return -1;
 }

希望这有助于某人。

几年后,但这种使用LINQ,返回-1,如果没有找到,不创建额外的对象,而的发现时,[而不是遍历整个IEnumerable的短路]:

public static int IndexOf<T>(this IEnumerable<T> list, T item)
{
    return list.Select((x, index) => EqualityComparer<T>.Default.Equals(item, x)
                                     ? index
                                     : -1)
               .FirstOr(x => x != -1, -1);
}

其中 'FirstOr' 是:

public static T FirstOr<T>(this IEnumerable<T> source, T alternate)
{
    return source.DefaultIfEmpty(alternate)
                 .First();
}

public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> predicate, T alternate)
{
    return source.Where(predicate)
                 .FirstOr(alternate);
}

以下事实之后找到索引的替代方法是包裹可枚举,有点类似于用LINQ的GroupBy()方法。

public static class IndexedEnumerable
{
    public static IndexedEnumerable<T> ToIndexed<T>(this IEnumerable<T> items)
    {
        return IndexedEnumerable<T>.Create(items);
    }
}

public class IndexedEnumerable<T> : IEnumerable<IndexedEnumerable<T>.IndexedItem>
{
    private readonly IEnumerable<IndexedItem> _items;

    public IndexedEnumerable(IEnumerable<IndexedItem> items)
    {
        _items = items;
    }

    public class IndexedItem
    {
        public IndexedItem(int index, T value)
        {
            Index = index;
            Value = value;
        }

        public T Value { get; private set; }
        public int Index { get; private set; }
    }

    public static IndexedEnumerable<T> Create(IEnumerable<T> items)
    {
        return new IndexedEnumerable<T>(items.Select((item, index) => new IndexedItem(index, item)));
    }

    public IEnumerator<IndexedItem> GetEnumerator()
    {
        return _items.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

其中给出的使用情况:

var items = new[] {1, 2, 3};
var indexedItems = items.ToIndexed();
foreach (var item in indexedItems)
{
    Console.WriteLine("items[{0}] = {1}", item.Index, item.Value);
}

今天这个偶然发现在答案的追寻,我想我会我的版本添加到列表(没有双关语意)。它utlises的C#6.0

空条件运算符
IEnumerable<Item> collection = GetTheCollection();

var index = collection
.Select((item,idx) => new { Item = item, Index = idx })
//or .FirstOrDefault(_ =>  _.Item.Prop == something)
.FirstOrDefault(_ => _.Item == itemToFind)?.Index ?? -1;

我已经做了一些(测试)和大集合(〜100,000),最坏的情况下你想要的产品,在年底“老马的赛车”,这是 2倍快比做ToList().FindIndex()。如果你想要的项目,在中间的〜4倍更快。

有关较小集合(〜10,000)这似乎是仅稍快

下面有我如何测试了它的 https://gist.github.com/insulind/16310945247fcf13ba186a45734f254e

使用@Marc Gravell的回答,我发现了一种用下面的方法:

source.TakeWhile(x => x != value).Count();

为了得到-1当物品无法找到:

internal static class Utils
{

    public static int IndexOf<T>(this IEnumerable<T> enumerable, T item) => enumerable.IndexOf(item, EqualityComparer<T>.Default);

    public static int IndexOf<T>(this IEnumerable<T> enumerable, T item, EqualityComparer<T> comparer)
    {
        int index = enumerable.TakeWhile(x => comparer.Equals(x, item)).Count();
        return index == enumerable.Count() ? -1 : index;
    }
}

我想这样才能既最快和简单。但是,我没有测试表演呢。

此可以得到具有扩展(作为代理的作用)非常酷,例如:

collection.SelectWithIndex(); 
// vs. 
collection.Select((item, index) => item);

这将自动地分配指标通过此Index属性访问的集合。

接口:

public interface IIndexable
{
    int Index { get; set; }
}

自定义扩展名(EF与和工作的DbContext可能是最有用的):

public static class EnumerableXtensions
{
    public static IEnumerable<TModel> SelectWithIndex<TModel>(
        this IEnumerable<TModel> collection) where TModel : class, IIndexable
    {
        return collection.Select((item, index) =>
        {
            item.Index = index;
            return item;
        });
    }
}

public class SomeModelDTO : IIndexable
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }

    public int Index { get; set; }
}

// In a method
var items = from a in db.SomeTable
            where a.Id == someValue
            select new SomeModelDTO
            {
                Id = a.Id,
                Name = a.Name,
                Price = a.Price
            };

return items.SelectWithIndex()
            .OrderBy(m => m.Name)
            .Skip(pageStart)
            .Take(pageSize)
            .ToList();
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top