How to Get the Index of an Element in an Ienumerable

How to get the index of an element in an IEnumerable?

The whole point of getting things out as IEnumerable is so you can lazily iterate over the contents. As such, there isn't really a concept of an index. What you are doing really doesn't make a lot of sense for an IEnumerable. If you need something that supports access by index, put it in an actual list or collection.

How to get item from IEnumerable collection using its index in C#?


For example, if index = 3, it should provide me 3rd item of the
IEnumerable

You know that indexes are zero based in .NET? However, you can use ElementAt:

Customer c = customerList.ElementAt(currentIndex); // 4th

Use ElementAtOrDefault to prevent an exception if there are not enough items, then you get null:

Customer c = customerList.ElementAtOrDefault(currentIndex); // 4th or null

These methods are optimized in a way that they use the IList<T> indexer. So in your example there is actually an Customer[] which implements that interface, hence it will use the indexer.

If the sequence does not implement IList<T> it will be enumerated to find the item at this index.

How to access index in IEnumerable object in C#?


var myProducts = Models.Products.ToList();
for(i=0; i< myProducts.Count ; i++)
{
//myProducts[i];
}

Index or Position of a string within an list of ienumerable strings

Well, since IEnumerables are used for enumerations, it's not such a surprise they don't have an IndexOf method. You can create an extension method if you want.

However, since you're already enumerating, what's the point of calculating the index again? Do something like this:

int index = 0;
foreach(var test in TitleNames)
{
if(...) return index;
index++;
}

Come to think of it, this is the extension method you want:

public static int IndexOf(this IEnumerable<T> list, T item)
{
int index = 0;
foreach(var l in list)
{
if(l.Equals(item))
return index;
index++;
}
return -1;
}

Just remember to add checks for nulls, and maybe supply an optional comparer.

How to get Index of IEnumerable SelectList?

This will give you an ordered list with indexes

    List<string> selectListName = new List<String>();
selectListName.Add("Ohio");
selectListName.Add("Maine");
selectListName.Add("Texas");
selectListName.Add("Oregon");
selectListName.Add("Alabama");

var result2 = selectListName.Select( (state, index) => new { index, state
}).OrderBy(a=>a.state).ToList();
foreach(var b in result2)
{
Console.WriteLine( b.index + " " + b.state) ;
}

result: If you re looking for the existing index
4 Alabama
1 Maine
0 Ohio
3 Oregon
2 Texas

To use the result
Console.WriteLine(result2.FirstOrDefault(a=>a.state.Equals("Ohio")).index);
2
Console.WriteLine(result2.FirstOrDefault(a=>a.index.Equals(2)).state);
Ohio


To get this result: 
0 Alabama
1 Maine
2 Ohio
3 Oregon
4 Texas

Order first, then index as shown below
var result2 = selectListName.OrderBy(a=>a).Select( (state, index) => new { index,
state }).ToList();
foreach(var b in result2)
{
Console.WriteLine( b.index + " " + b.state) ;
}

Find First Index of IEnumerable

As @MartinLiversage pointed out, there is an overload of Array.CreateInstance allowing to specify a lower bound:

public static Array CreateInstance (Type elementType, int[] lengths, int[] lowerBounds);

You have to cast the unspecific Array to a concrete type, to able to access its elements directly. Example:

var cells =
(int[,])Array.CreateInstance(typeof(int), new[] { ROWS, COLUMNS }, new[] { 1, 1 });

You can get the bounds with cells.GetLowerBound(0) (first dimension) and cells.GetLowerBound(1) (second dimension). There is a corresponding GetUpperBound method. Example:

// Loop through the matrix
for (int i = cells.GetLowerBound(0); i <= cells.GetUpperBound(0); i++) {
for (int j = cells.GetLowerBound(1); j <= cells.GetUpperBound(1); j++) {
// Get an element
var element = cells[i, j];

// Set an element
cells[i, j] = value;
}
}

Or, to get the first element only:

var result = cells[cells.GetLowerBound(0), cells.GetLowerBound(1)];

You can also enumerate the array with foreach. This flattens the array, i.e. it treats the array as if it was one-dimensional.

Note, the LINQ extension method First always returns the first item, irrespective of the lower bounds of the array.

var result = cells.First();

IEnumerable.Select with index

I'm not sure what kind of index you're looking for, but if it's just set of consecutive numbers then you're lucky. There is Select overload that does exactly that:

return accidents.Select((t, i) => new Accident() {Id = i, Name = t.Replace("\"", string.Empty)}).ToArray();

It expects a delegate that takes two parameters - the item and its index.

How to get index using LINQ?

An IEnumerable is not an ordered set.

Although most IEnumerables are ordered, some (such as Dictionary or HashSet) are not.

Therefore, LINQ does not have an IndexOf method.

However, you can write one yourself:

///<summary>Finds the index of the first item matching an expression in an enumerable.</summary>
///<param name="items">The enumerable to search.</param>
///<param name="predicate">The expression to test the items against.</param>
///<returns>The index of the first matching item, or -1 if no items match.</returns>
public static int FindIndex<T>(this IEnumerable<T> items, Func<T, bool> predicate) {
if (items == null) throw new ArgumentNullException("items");
if (predicate == null) throw new ArgumentNullException("predicate");

int retVal = 0;
foreach (var item in items) {
if (predicate(item)) return retVal;
retVal++;
}
return -1;
}
///<summary>Finds the index of the first occurrence of an item in an enumerable.</summary>
///<param name="items">The enumerable to search.</param>
///<param name="item">The item to find.</param>
///<returns>The index of the first matching item, or -1 if the item was not found.</returns>
public static int IndexOf<T>(this IEnumerable<T> items, T item) { return items.FindIndex(i => EqualityComparer<T>.Default.Equals(item, i)); }

How do I get the first element from an IEnumerable T in .net?

If you can use LINQ you can use:

var e = enumerable.First();

This will throw an exception though if enumerable is empty: in which case you can use:

var e = enumerable.FirstOrDefault();

FirstOrDefault() will return default(T) if the enumerable is empty, which will be null for reference types or the default 'zero-value' for value types.

If you can't use LINQ, then your approach is technically correct and no different than creating an enumerator using the GetEnumerator and MoveNext methods to retrieve the first result (this example assumes enumerable is an IEnumerable<Elem>):

Elem e = myDefault;
using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) {
if (enumer.MoveNext()) e = enumer.Current;
}

Joel Coehoorn mentioned .Single() in the comments; this will also work, if you are expecting your enumerable to contain exactly one element - however it will throw an exception if it is either empty or larger than one element. There is a corresponding SingleOrDefault() method that covers this scenario in a similar fashion to FirstOrDefault(). However, David B explains that SingleOrDefault() may still throw an exception in the case where the enumerable contains more than one item.

Edit: Thanks Marc Gravell for pointing out that I need to dispose of my IEnumerator object after using it - I've edited the non-LINQ example to display the using keyword to implement this pattern.



Related Topics



Leave a reply



Submit