Count Iteration on the Enumerable Cycle

Linq Performance: (ElementAt,Count) vs (foreach)

The ElementAt() method is O(n), unless the actual concrete class that the IEnumerable represents optimizes it. That means that every time you call it, it has to loop through the entire Enumerable to find the element at n. Not to mention that since you have i < result.Count() in the condition part of your for loop, it's gotta loop through the entire enumerable every single time to get that count.

The second way, you loop through result exactly once.

Is there a way to access an iteration-counter in Java's for-each loop?

No, but you can provide your own counter.

The reason for this is that the for-each loop internally does not have a counter; it is based on the Iterable interface, i.e. it uses an Iterator to loop through the "collection" - which may not be a collection at all, and may in fact be something not at all based on indexes (such as a linked list).

Why does Enumerable.Single() iterate all elements, even when more than one item has already been found?

You didn't seem to be the only one thinking that. The .NET Core implementation has an optimized version:

using (IEnumerator<TSource> e = source.GetEnumerator())
{
while (e.MoveNext())
{
TSource result = e.Current;
if (predicate(result))
{
while (e.MoveNext())
{
if (predicate(e.Current))
{
throw Error.MoreThanOneMatch();
}
}

return result;
}
}
}

So to answer your question: there doesn't seem to be a 'good' reason, other than just a developer not thinking about optimizing this use case.

Count the items from a IEnumerableT without iterating?

IEnumerable doesn't support this. This is by design. IEnumerable uses lazy evaluation to get the elements you ask for just before you need them.

If you want to know the number of items without iterating over them you can use ICollection<T>, it has a Count property.

How do you get the index of the current iteration of a foreach loop?

The foreach is for iterating over collections that implement IEnumerable. It does this by calling GetEnumerator on the collection, which will return an Enumerator.

This Enumerator has a method and a property:

  • MoveNext()
  • Current

Current returns the object that Enumerator is currently on, MoveNext updates Current to the next object.

The concept of an index is foreign to the concept of enumeration, and cannot be done.

Because of that, most collections are able to be traversed using an indexer and the for loop construct.

I greatly prefer using a for loop in this situation compared to tracking the index with a local variable.

Foreach loop doesn't iterate over entire IEnumerable

An IEnumerable is an iterator, so it returns one result at a time.

Each time foreach loops, it asks the iterator for the next result. Sometimes results can disappear from the collection being enumerated, so you get unexpected behaviour.

To avoid this, make sure you have all the results before starting the foreach, by calling .ToList()

  // Make a list of all documents
List<Document> documentsToAdd;

documentsToAdd = dbEvent.Documents
.Where(dbd => !eventToSave.Documents
.Select(d => d.DocumentId)
.Contains(dbd.DocumentId))
.ToList(); // load all results

// Now this will loop through the whole list
foreach (Document documentToAdd in documentsToAdd)
{
documentToAdd.DocumentType = null;
documentToAdd.DeletedByUser = null;
documentToAdd.DocumentOwnerTeam = null;
documentToAdd.UploadedByUser = null;
documentToAdd.UploadedInStage = null;

hcDbContext.Documents.Add(documentToAdd);
}

How to iterate a loop every n items

You can also do this with LINQ:

var largeList = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
for (int i = 0; i < largeList.Count; i += 3)
{
var items = largeList.Skip(i).Take(3).ToList();
// do stuff with your 3 (or less items)
}

Enumerator consisting of a repeating (but changing) array

Try this one

enum = Enumerator.new do |y|
lap = 1
ss = %w(Start Peak Finish).cycle
loop do
3.times { y << "#{ss.next} Lap #{lap}" }
lap += 1
end
end

enum.first(7)
=> ["Start Lap 1", "Peak Lap 1", "Finish Lap 1", "Start Lap 2", "Peak Lap 2", "Finish Lap 2", "Start Lap 3"]


Related Topics



Leave a reply



Submit