Reputation: 3955
I have a foreach loop in which I need to verify whether the element is last in the collection I'm iterating on. What I've tried:
foreach (var character in list) // list is of type `string`
{
if (character == list.Last())
{
}
}
But in this case if I have "la la la"
the if
statement will execute on a second character.
Question: How to write the if
statement so that it will execute when accessing the last element of a sequence?
Upvotes: 3
Views: 2542
Reputation: 98740
foreach (var character in list) // list is of type `string`
{
if (character == list[list.Count - 1])
{
}
}
Here is a DEMO
.
As an alternative, since List
implements IEnumerable
interface, you can use Enumerable.Last
method
Returns the last element of a sequence.
foreach (var character in list) // list is of type `string`
{
if (character == list.Last())
{
}
}
Here is a DEMO
.
Upvotes: 3
Reputation: 45071
If you only have an IEnumerable
, you have to manually trigger the enumerator. Here is a sample extension method which maybe helps you:
public static class IEnumerableExtensions
{
public static void Action<T>(this IEnumerable<T> source, Action<T> sequenceElement, Action<T> lastElement)
{
if (source == null)
throw new ArgumentNullException("source");
if (sequenceElement == null)
throw new ArgumentNullException("sequenceElement");
if (lastElement == null)
throw new ArgumentNullException("lastElement");
T element = default(T);
using (var enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
element = enumerator.Current;
while (enumerator.MoveNext())
{
sequenceElement(element);
element = enumerator.Current;
}
lastElement(element);
}
}
}
You can then call it this way:
var myElements = Enumerable.Range(1, 10);
myElements.Action(value => Console.WriteLine("Something out of the sequence: " + value),
value => Console.WriteLine("The last element: " + value));
Upvotes: 0
Reputation: 109537
If you find yourself doing this kind of thing often, you can use an extension method which will let you ask if an element in a sequence is the last item.
This was originally written by Jon Skeet; he called it "Smart Enumerable", and I believe it is part of the MoreLinq Linq Extensions (also by Jon Skeet).
If you do use such a thing, your code would looks something like this:
foreach (var character in list.AsSmartEnumerable())
if (character.IsLast)
// Do something with character.Value
Here's a slightly modified copy of Jon Skeet's implementation:
/// <summary>
/// Static class to make creation easier. If possible though, use the extension
/// method in SmartEnumerableExt.
/// </summary>
public static class SmartEnumerable
{
/// <summary> method to make life easier.</summary>
/// <typeparam name="T">Type of enumerable</typeparam>
/// <param name="source">Source enumerable</param>
/// <returns>A new SmartEnumerable of the appropriate type</returns>
public static SmartEnumerable<T> Create<T>(IEnumerable<T> source)
{
return new SmartEnumerable<T>(source);
}
}
/// <summary>Wrapper methods for SmartEnumerable[T].</summary>
public static class SmartEnumerableExt
{
/// <summary>Extension method to make life easier.</summary>
/// <typeparam name="T">Type of enumerable</typeparam>
/// <param name="source">Source enumerable</param>
/// <returns>A new SmartEnumerable of the appropriate type</returns>
public static SmartEnumerable<T> AsSmartEnumerable<T>(this IEnumerable<T> source)
{
return new SmartEnumerable<T>(source);
}
}
/// <summary>
/// Type chaining an IEnumerable<T> to allow the iterating code
/// to detect the first and last entries simply.
/// </summary>
/// <typeparam name="T">Type to iterate over</typeparam>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="This is too general to end in 'Collection'")]
public class SmartEnumerable<T>: IEnumerable<SmartEnumerable<T>.Entry>
{
/// <summary>Enumerable to which we proxy</summary>
readonly IEnumerable<T> _enumerable;
/// <summary>Constructor.</summary>
/// <param name="enumerable">Collection to enumerate. Must not be null.</param>
public SmartEnumerable(IEnumerable<T> enumerable)
{
if (enumerable==null)
{
throw new ArgumentNullException("enumerable");
}
this._enumerable = enumerable;
}
/// <summary>
/// Returns an enumeration of Entry objects, each of which knows
/// whether it is the first/last of the enumeration, as well as the
/// current value.
/// </summary>
public IEnumerator<Entry> GetEnumerator()
{
using (IEnumerator<T> enumerator = _enumerable.GetEnumerator())
{
if (!enumerator.MoveNext())
{
yield break;
}
bool isFirst = true;
bool isLast = false;
int index = 0;
while (!isLast)
{
T current = enumerator.Current;
isLast = !enumerator.MoveNext();
yield return new Entry(isFirst, isLast, current, index++);
isFirst = false;
}
}
}
/// <summary>Non-generic form of GetEnumerator.</summary>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Represents each entry returned within a collection,
/// containing the value and whether it is the first and/or
/// the last entry in the collection's. enumeration
/// </summary>
public class Entry
{
internal Entry(bool isFirst, bool isLast, T value, int index)
{
this._isFirst = isFirst;
this._isLast = isLast;
this._value = value;
this._index = index;
}
/// <summary>The value of the entry.</summary>
public T Value
{
get
{
return _value;
}
}
/// <summary>Whether or not this entry is first in the collection's enumeration.</summary>
public bool IsFirst
{
get
{
return _isFirst;
}
}
/// <summary>Whether or not this entry is last in the collection's enumeration.</summary>
public bool IsLast
{
get
{
return _isLast;
}
}
/// <summary>The 0-based index of this entry (i.e. how many entries have been returned before this one)</summary>
public int Index
{
get
{
return _index;
}
}
readonly bool _isFirst;
readonly bool _isLast;
readonly T _value;
readonly int _index;
}
}
Upvotes: 0
Reputation: 110
If you only want to do an action on the last character, then Mare Infinitus' code should do the trick.
What about:
var elementList = list.Split(" ");
if (elementList.Last().Equals(character))
{
// do something here
}
this should do it, no need for foreach.
However, if you want to loop and do a specific action for the last character, then you can use a standard for
loop. James' answer:
for (int i = 0; i <= list.Count-1; i++)
{
if (i == list.Count-1)
{
// so something special with last item
}
}
Upvotes: 0
Reputation: 4573
Since your list is actually a string, you need to convert it into a list.
var elementList = list.Split(" ");
You can then find the last element.
var lastElement = elementList.LastOrDefault();
Just check using IsNullOrEmpty to handle the case of an empty list.
Upvotes: 0
Reputation: 82096
I would advise iterating using the index rather than the object reference i.e.
for (int i = 0; i <= list.Count-1; i++)
{
if (i == list.Count-1)
{
// so something special with last item
}
}
Upvotes: 12