如何在 foreach 循环中验证元素是不是在集合中的最后一个?
Posted
技术标签:
【中文标题】如何在 foreach 循环中验证元素是不是在集合中的最后一个?【英文标题】:How to verify in a foreach loop whether the element is last in the collection?如何在 foreach 循环中验证元素是否在集合中的最后一个? 【发布时间】:2013-04-15 05:19:54 【问题描述】:我有一个 foreach 循环,我需要在其中验证元素是否在我正在迭代的集合中的最后一个。我试过的:
foreach (var character in list) // list is of type `string`
if (character == list.Last())
但在这种情况下,如果我有"la la la"
,if
语句将在第二个字符上执行。
问题:如何编写if
语句以便在访问序列的最后一个元素时执行?
【问题讨论】:
那么“la la la”是一个字符串吗?list
是什么?
然后用繁体的for作为回答
你为什么要这样做?您是想对除最后一个元素之外的所有元素执行操作,还是只更新最后一个元素?
@AlekseiChepovoi 也许这有点XY Problem。我假设您根据逗号之类的字符拆分字符串,然后将每个子字符串传递给可以确定类型的东西?需要识别最后一项是因为需要关闭最终类型?
@AlekseiChepovoi 你能不能不做类似"1,2,3,4".Split(',').Select(eachString => ToInt(eachString)).ToList()
的事情?这将避免很多其他的跑腿工作。
【参考方案1】:
我建议使用索引而不是对象引用进行迭代,即
for (int i = 0; i <= list.Count-1; i++)
if (i == list.Count-1)
// so something special with last item
【讨论】:
还是只处理循环内除最后一个以外的所有内容,并在循环外处理最后一个? @RogerRowland 也是如此,但是,将其作为一般迭代的一部分进行意味着您可以一口气完成所有操作。 OP还特别询问了如何在inside循环中进行操作。 为什么要迭代,没有它也可以轻松完成,看我的回答 @MareInfinitus 是的,当您不需要处理列表中的其他项目时,这一切都很好...... OP 说“我需要验证该元素是集合中的最后一个我正在迭代”。 @MareInfinitus 除了@James 所说的,如果您事先不知道列表中的最后一个字符怎么办?我怀疑.Last()
无论如何都会以与此解决方案相同的方式在内部进行枚举..【参考方案2】:
foreach (var character in list) // list is of type `string`
if (character == list[list.Count - 1])
这是DEMO
。
作为替代方案,由于List
实现了IEnumerable
接口,您可以使用Enumerable.Last
方法
返回序列的最后一个元素。
foreach (var character in list) // list is of type `string`
if (character == list.Last())
这是DEMO
。
【讨论】:
我需要验证当前字符是否是序列中的最后一个字符,但是这个“if”验证当前字符是否等于最后一个字符 @AlekseiChepovoi 我不明白你的评论。你的意思是你检查当前的char
是List
的最后一个char
吗?【参考方案3】:
由于您的列表实际上是一个字符串,因此您需要将其转换为列表。
var elementList = list.Split(" ");
然后您可以找到最后一个元素。
var lastElement = elementList.LastOrDefault();
只需检查使用 IsNullOrEmpty 处理空列表的情况。
【讨论】:
【参考方案4】:如果您只想对最后一个字符执行操作,那么 Mare Infinitus' 代码应该可以解决问题。
怎么样:
var elementList = list.Split(" ");
if (elementList.Last().Equals(character))
// do something here
应该可以,不需要foreach。
但是,如果您想循环并对最后一个字符执行特定操作,则可以使用标准的for
循环。 James'答案:
for (int i = 0; i <= list.Count-1; i++)
if (i == list.Count-1)
// so something special with last item
【讨论】:
【参考方案5】:如果你发现自己经常做这种事情,你可以使用扩展方法,让你询问序列中的元素是否是最后一项。
这最初是由 Jon Skeet 写的; he called it "Smart Enumerable",我相信它是 MoreLinq Linq Extensions 的一部分(也是 Jon Skeet)。
如果您确实使用了这样的东西,您的代码将如下所示:
foreach (var character in list.AsSmartEnumerable())
if (character.IsLast)
// Do something with character.Value
这是 Jon Skeet 实现的稍作修改的副本:
/// <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;
【讨论】:
对我来说会显得有点矫枉过正。如果我到处都在做这种事情,我可能只会创建一个简单的ForEach
扩展方法,它会简单地迭代列表并为最后一项引发回调方法。看看这种方法是否比AsSmartEnumerable
更快会很有趣。
@James 是的,如果这是 SmartEnumerable 给你的全部,我同意 - 但它也会给你当前项目的索引,以及它是否是第一个项目列表。我们确实在不同的地方使用它,它使代码更具可读性(特别是当我们使用项目的索引时,否则必须在 foreach
循环之前声明一个索引计数器并在循环中递增它)跨度>
【参考方案6】:
如果您只有IEnumerable
,则必须手动触发枚举器。这是一个示例扩展方法,可能对您有所帮助:
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);
你可以这样称呼它:
var myElements = Enumerable.Range(1, 10);
myElements.Action(value => Console.WriteLine("Something out of the sequence: " + value),
value => Console.WriteLine("The last element: " + value));
【讨论】:
以上是关于如何在 foreach 循环中验证元素是不是在集合中的最后一个?的主要内容,如果未能解决你的问题,请参考以下文章