[英]How to compare sequential elements in a foreach loop in C#
In a foreach loop I want to compare an element with the previous element that was read.在 foreach 循环中,我想将一个元素与读取的前一个元素进行比较。 How can I do that?
我该怎么做? What is the syntax for addressing a previous element in a foreach loop?
在 foreach 循环中寻址前一个元素的语法是什么?
You don't have that option built in with a foreach
loop.您没有使用
foreach
循环内置该选项。
You can either switch to a for
loop or use a variable.您可以切换到
for
循环或使用变量。
Suppose you iterate through a list of objects, these are your options:假设您遍历一个对象列表,这些是您的选择:
object prev = null;
foreach(var current in myListOfObjects)
{
if(current == prev)
{
// do stuff
}
// don't forget the next row!
prev = current;
}
or或
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
}
}
Everything is better with
Bluetooth
extension methods:使用
蓝牙
扩展方法一切都更好:
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);
}
You might need to tweak this depending on how you want first and last elements handled.您可能需要根据您希望如何处理第一个和最后一个元素来调整它。
You can loop over a bit modified source
instead of initial, say ListOfMyObjects
:您可以遍历稍微修改过的
source
而不是初始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;
});
So you can loop所以你可以循环
foreach(var item in source) {
if (item.Prior == item.Current) {
...
}
}
A foreach
itself has no syntax 'for addressing a previous element'. foreach
本身没有“用于寻址前一个元素”的语法。 There are two options, depending on the characteristics of the collection and also the notion of a 'previous' element in respect of the first one.有两种选择,具体取决于集合的特征以及关于第一个元素的“先前”元素的概念。 The following the examples are a little bit simplistic, but you should be able to choose the right path and fine-tune the details.
下面的例子有点简单,但你应该能够选择正确的路径并微调细节。
Works well if there's no cheap (performance-wise) way to index elements in the sequence, and you are OK with 'pretending' there's an empty ( null
, or default(T)
) item before the very first item.如果没有廉价(性能方面)索引序列中元素的方法,则效果很好,并且您可以“假装”在第一个项目之前有一个空(
null
或default(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;
}
Note that if T is a value type, your would be actually copying the values themselves.请注意,如果 T 是值类型,则您实际上是在复制值本身。
for
loop and indexingfor
循环和索引Works well if there is a cheap (performance-wise) way to index individual elements directly.工作得很好,如果有一个便宜的(性能代价)的方式来直接索引单个元素。
List<T>
and arrays are good examples here. 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
}
Similar to using a temp variable, however this solution moves the scope of the temp variable inside the loop类似于使用临时变量,但是此解决方案将临时变量的范围移动到循环内
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];
}
}
As mentioned by Pham X, one easy way to do this would be a temp variable.正如 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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.