3

我有一个 foreach 循环,我需要在其中验证元素是否是我正在迭代的集合中的最后一个。我试过的:

foreach (var character in list) // list is of type `string` 
{
    if (character == list.Last())
    {

    }
}

但在这种情况下,如果我有"la la la"if语句将在第二个字符上执行。

问题:如何编写if语句以便在访问序列的最后一个元素时执行?

4

6 回答 6

11

我建议使用索引而不是对象引用进行迭代,即

for (int i = 0; i <= list.Count-1; i++)
{
    if (i == list.Count-1)
    {
        // so something special with last item
    }
}
于 2013-04-22T10:32:33.000 回答
3
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.

于 2013-04-22T10:41:42.570 回答
0

由于您的列表实际上是一个字符串,因此您需要将其转换为列表。

var elementList = list.Split(" ");

然后您可以找到最后一个元素。

var lastElement = elementList.LastOrDefault();

只需检查使用 IsNullOrEmpty 来处理空列表的情况。

于 2013-04-22T10:37:54.100 回答
0

如果你发现自己经常做这种事情,你可以使用扩展方法,让你询问序列中的元素是否是最后一项。

这最初是由 Jon Skeet 写的;他称它为“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&lt;T&gt; 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;
    }
}
于 2013-04-22T10:41:10.840 回答
0

如果您只想对最后一个字符执行操作,那么Mare Infinitus的代码应该可以解决问题。

关于什么:

var elementList = list.Split(" ");
if (elementList.Last().Equals(character))
{
   // do something here
}

这应该这样做,不需要foreach。

但是,如果您想循环并为最后一个字符执行特定操作,则可以使用标准for循环。詹姆斯的回答:

for (int i = 0; i <= list.Count-1; i++)
{
    if (i == list.Count-1)
    {
        // so something special with last item
    }
}
于 2013-04-22T10:45:38.107 回答
0

如果您只有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));
于 2013-04-22T10:52:55.100 回答