如何在C#中比较foreach循环中的顺序元素

时间:2016-05-17 15:23:22

标签: c# foreach

在foreach循环中,我想将元素与之前读取的元素进行比较。我怎样才能做到这一点?在foreach循环中寻址前一个元素的语法是什么?

谢谢!

6 个答案:

答案 0 :(得分:7)

您没有使用foreach循环内置该选项 您可以切换到for循环或使用变量。

假设您遍历对象列表,这些是您的选择:

object prev = null;
foreach(var current in myListOfObjects)
{
    if(current == prev)
    {
        // do stuff
    }

    // don't forget the next row!
    prev = current;
}

for(var i = 1; i < myListOfObjects.count, i++) // Note: starting from 1 to avoid another condition inside the loop.
{
    if(myListOfObjects[i] == myListOfObjects[i-1])
    {
        // do stuff
    }
}

答案 1 :(得分:5)

使用蓝牙扩展方法,一切都更好:

public static class EnumerableExtensions
{
    public struct CurrentAndPrevious<T>
    {
        public T Current { get; private set; }
        public T Previous { get; private set; }

        public CurrentAndPrevious(T current, T previous) : this()
        {
            Previous = previous;
            Current = current;
        }
    }

    public static IEnumerable<CurrentAndPrevious<T>> WithPrevious<T>(this IEnumerable<T> enumerable)
    {
        var previous = default(T);

        using(var enumerator = enumerable.GetEnumerator())
        {
            while(enumerator.MoveNext())
            {
                yield return new CurrentAndPrevious<T>(enumerator.Current, previous);
                previous = enumerator.Current;
            }
        }
    }
}

var items = new[] { 1, 2, 3, 4, 5 };
foreach(var item in items.WithPrevious())
{
    Console.WriteLine(item.Previous + " " + item.Current);
}

您可能需要根据您希望处理第一个和最后一个元素的方式进行调整。

答案 2 :(得分:1)

你可以循环修改source而非首字母,比如说ListOfMyObjects

MyObject prior = default(MyObject);

var source = ListOfMyObjects
  .Select(item => {
     var result = new {
       Current = item,
       Prior = prior, 
     };

     prior = item; // side effect, not a good practice

     return result;  
  });

所以你可以循环

foreach(var item in source) {
  if (item.Prior == item.Current) {
    ...
  }
}

答案 3 :(得分:0)

foreach本身有 no 语法&#39;用于寻址前一个元素&#39;。有两种选择,取决于集合的特征以及之前的概念。关于第一个的要素。以下示例有点简单,但您应该能够选择正确的路径并对细节进行微调。

选项1:使用临时变量

如果没有便宜(以性能为导向)的方法来索引序列中的元素,那么你可以很好地使用&#39;假装&#39;在第一个项目之前有一个空(nulldefault(T))项。

T previous = default(T);  // corresponds to null for reference types
foreach (T item in sequence)
{
     … work with previous and item here…

     // the current 'item' is the new 'previous' for the next iteration
     previous = item;
}

请注意,如果T是值类型,您实际上将复制值本身。

选项2:使用for循环和索引

如果 是一种廉价(以性能为导向)直接索引单个元素的方法,那么效果很好。 List<T>和数组就是很好的例子。

// indexing from 1, i.e. from the second item in the sequence
for (int i = 1; i < sequence.Count; i++)
{
    var previous = sequence[i-1]; // this is obviously the previous item
    var current = sequence[i];    // this is obviously the current item
}

答案 4 :(得分:0)

与使用临时变量类似,但是此解决方案将临时变量的范围移动到循环

var collection = new List<int>() { 1, 2, 3, 4, 5 };

foreach (var item in collection)
{
    var currentIndex = collection.IndexOf(item);
    if (currentIndex > 0 && currentIndex < collection.Count)
    {
        var previousItem = collection[currentIndex - 1];
    }
}

答案 5 :(得分:-1)

正如Pham X所提到的,一个简单的方法就是临时变量。

ObjectType temp_object = null;
foreach(var entry in ListOfObjects)
{
    if(temp_object==null)
    {
        //this is the first time through...
        temp_object=entry;
    }
    else
    {
        //it's anything after the first loop
        if(entry==temp_object) Console.WriteLine("There is a match between two entries.");
        else temp_object=entry;
    }
}