C# 是否可以在foreach循环中增加标识符而不计算其表达式?
我有一个对象的集合,我想通过迭代来最终识别某种类型的模式。目前,我有一组if语句来检查表达式的标志。例如,我有一些类似于if(!foundFirstObjectOfTypeA)的东西。一旦我找到类型A的第一个对象,我会将标志设置为true,我们将不再执行该块并继续执行下一个块。我有几种类型的模式需要识别,正因为如此,它创建了一大块难以理解且丑陋的if语句 是否有一种方法可以在不计算foreach循环中的表达式的情况下查看/查看标识符?如果我可以按照If(identifer==ObjectA&&identifer.next==ObjectB)的思路做一些事情,那么我的代码将更可读、更容易理解,而且我可以处理而不必设置标志C# 是否可以在foreach循环中增加标识符而不计算其表达式?,c#,C#,我有一个对象的集合,我想通过迭代来最终识别某种类型的模式。目前,我有一组if语句来检查表达式的标志。例如,我有一些类似于if(!foundFirstObjectOfTypeA)的东西。一旦我找到类型A的第一个对象,我会将标志设置为true,我们将不再执行该块并继续执行下一个块。我有几种类型的模式需要识别,正因为如此,它创建了一大块难以理解且丑陋的if语句 是否有一种方法可以在不计算foreach循环中的表达式的情况下查看/查看标识符?如果我可以按照If(identifer==ObjectA&&i
如果没有直接的方法/途径,有人有没有聪明的变通方法来模拟我想要的效果?使用
for
循环来增加I
,然后只看对象[I]
和对象[I+1]
。您使用的是哪种类型的集合?名单?阵列?一个foreach
循环所做的就是对您隐藏计数器。如果我了解你的情况,绝对没有理由使用foreach
循环而不是for
循环
这适用于任何列表和任何对象序列:
功能:
public static bool ContainsSequence
(System.Collections.Generic.IList<object> list, params object[] seq)
{
for (int i = 0; i < list.Count() - seq.Count() + 1; i++)
{
int j;
for (j = 0; j < seq.Count(); j++)
{
if (list[i + j] != seq[j])
break;
}
if (j == seq.Count())
return true;
}
return false;
}
private static void Main(string[] args)
{
var A = new object();
var B = new object();
var C = new object();
var D = new object();
var list = new[] {A, B, C, D};
Console.WriteLine(ContainsSequence(list, B, C, D));
Console.WriteLine(ContainsSequence(list, A, D, C, B, A, C));
Console.WriteLine(ContainsSequence(list, A, B));
}
True
False
True
输出:
public static bool ContainsSequence
(System.Collections.Generic.IList<object> list, params object[] seq)
{
for (int i = 0; i < list.Count() - seq.Count() + 1; i++)
{
int j;
for (j = 0; j < seq.Count(); j++)
{
if (list[i + j] != seq[j])
break;
}
if (j == seq.Count())
return true;
}
return false;
}
private static void Main(string[] args)
{
var A = new object();
var B = new object();
var C = new object();
var D = new object();
var list = new[] {A, B, C, D};
Console.WriteLine(ContainsSequence(list, B, C, D));
Console.WriteLine(ContainsSequence(list, A, D, C, B, A, C));
Console.WriteLine(ContainsSequence(list, A, B));
}
True
False
True
如果您知道要查找多少个对象,则该函数可以变得更简单(如果您只查找两个对象,则这几乎是用户的答案-您只需添加AndrewS的边界检查,如下所示)
如果需要序列开头的索引,可以将my函数的返回类型更改为int,并返回
i
而不是true
(返回-1
而不是false
)如果使用for循环,可以这样做
for (int i = 0; i < list.Count - 1; i++)
if (list[i] == ObjectA && list[i + 1] == ObjectB)
; // Your code
for(int i=0;i
我认为没有直接的支持,但您可以随时模仿
例如(解决方案的一部分):
静态IEnumerable topeakable(此IEnumerable流)
{
T prev=
foreach(流中的T项)
{
收益率返回新的可查看(上一个,项目);
prev=项目;
}
收益率返回新的可查看(项目,默认值(T));
}
更新:缺少零件
class Peekable<T>
{
public Peekable(T current, T next)
{
Current = current;
Next = next;
}
public T Current { get; private set; }
public T Next { get; private set; }
}
static class PeekableAdaptor
{
public static IEnumerable<Peekable<T>> ToPeekable<T>(this IEnumerable<T> stream)
{
var source = stream.GetEnumerator();
if (!source.MoveNext())
yield break;
T prev = source.Current;
while (source.MoveNext())
{
yield return new Peekable<T>(prev, source.Current);
prev = source.Current;
}
yield return new Peekable<T>(prev, default(T));
}
}
class Program
{
static void Main(string[] args)
{
foreach (var pair in Enumerable.Range(1, 10).ToPeekable())
{
Console.WriteLine(pair.Current, pair.Next);
}
}
}
类可查看
{
可公开查看(T当前,T下一个)
{
电流=电流;
下一个=下一个;
}
公共T当前{get;私有集;}
公共T下一个{get;私有集;}
}
静态类可伸缩适配器
{
公共静态IEnumerable topeakable(此IEnumerable流)
{
var source=stream.GetEnumerator();
如果(!source.MoveNext())
屈服断裂;
T prev=电源电流;
while(source.MoveNext())
{
收益率返回新的可窥视值(上一个、源、当前);
prev=源电流;
}
收益率-收益率-新可窥视(上一个,默认值(T));
}
}
班级计划
{
静态void Main(字符串[]参数)
{
foreach(Enumerable.Range(1,10).ToPeekable()中的变量对)
{
Console.WriteLine(pair.Current,pair.Next);
}
}
}
IEnumerable
是一种非常轻的仅向前推进的
迭代器实现。如果你看一下,只有三个成员:
作为解决方案,您可以手动迭代IEnumerable
,也可以使用循环
bool MoveNext()
void Reset()
object Current
因此,唯一的操作是继续、重置和检索当前项。没有内置的能力来窥探接下来会发生什么
IEnumerable版本
bool someFlag=false;
IEnumerable collection=新对象[]{“string”,true,4,DateTime.Now};
使用(var enumerator=collection.GetEnumerator()){
while(true){
bool end=enumerator.MoveNext();
如果(!结束){
if(枚举数.Current.GetType()==typeof(字符串)){
end=enumerator.MoveNext();
if(!end&&enumerator.Current.GetType()==typeof(bool))
someFlag=true;
}
}
如果(结束)中断;
}
}
循环版本
bool someFlag=false;
列表集合=新对象[]{“string”,true,4,DateTime.Now};
int i=0;
while(true){
bool end=i
根据我的答案,我提出了一个可能的解决方案。这将适用于任何类型的收集;即使是那些无法索引的
foreach (var item in ForEachHelper.Wrap(collection))
{
Console.WriteLine("Position=" + item.Index.ToString());
Console.WriteLine("Current=" + item.Current.ToString());
if (item.HasNext)
{
Console.WriteLine("Next=" + item.Next.ToString());
}
}
这是相关的代码
public static class ForEachHelper
{
public sealed class Item<T>
{
public int Index { get; set; }
public T Current { get; set; }
public T Next { get; set; }
public bool HasNext { get; set; }
}
public static IEnumerable<Item<T>> Wrap<T>(IEnumerable<T> enumerable)
{
IEnumerator<T> enumerator = enumerable.GetEnumerator();
try
{
var item = new Item<T>();
item.Index = 0;
item.Current = default(T);
item.Next = default(T);
item.HasNext = false;
if (enumerator.MoveNext())
{
item.Current = enumerator.Current;
if (enumerator.MoveNext())
{
item.Next = enumerator.Current;
item.HasNext = true;
}
while (item.HasNext)
{
var next = new Item<T>();
next.Index = item.Index + 1;
next.Current = item.Next;
next.Next = default(T);
if (enumerator.MoveNext())
{
next.Next = enumerator.Current;
next.HasNext = true;
}
var current = item;
item = next;
yield return current;
}
yield return item;
}
}
finally
{
enumerator.Dispose();
}
}
}
公共静态类ForEachHelper
{
公共密封类物品
{
公共int索引{get;set;}
公共T当前{get;set;}
公共T下一个{get;set;}
公共bool HasNext{get;set;}
}
公共静态IEnumerable包装(IEnumerable enumerable)
{
IEnumerator枚举器=可枚举的.GetEnumerator();
尝试
{
var item=新项();
项目指数=0;
项目当前=默认值(T);
item.Next=默认值(T);
item.HasNext=false;
if(枚举数.MoveNext())
{
item.Current=枚举数.Current;
if(枚举数.MoveNext())
{
item.Next=枚举数.Current;
item.HasNext=true;
}
while(item.HasNext)
{
var next=新项();
下一个,Inde