Is it possible to increment an identifier in a foreach loop without evaluating its expression?

I have a set of objects that I would like to skip in order to eventually recognize some type of template. I currently have an if command that checks the flag for an expression. For example, I have something like if (! FoundFirstObjectOfTypeA) lines. As soon as I discovered the first object of type A, I would set the flag to true, and we would no longer execute the block and move on to the next block. I have several types of patterns for recognition, and because of this, he created a large block of if statements that are hard to understand and ugly.

Is there any way to peek / peek behind an identifier without evaluating an expression in a foreach loop? If I could do something along the if lines (identifier == ObjectA && identifer.next == ObjectB), this would make my code more readable and understandable, and I could handle it without having to set flags.

If there is no direct method / method, does anyone have some clever workarounds to mimic the effects that I want?

+3
source share
5 answers

for , i, object[i] object[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

, , ( , - AndrewS .)

, int i true ( -1 false.)

+6

, , .

( ):

  static IEnumerable<Peekable<T>> ToPeekable(this IEnumerable<T> stream)
  {
     T prev = <get first item, and move...>
     foreach(T item in stream)
     {
       yield return new Peekable<T>(prev, item);
       prev = item;
    }
    yield return new Peekable<T>(item, default(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);
        }
    }
}
+2

for, - .

for (int i = 0; i < list.Count - 1; i++)
    if (list[i] == ObjectA && list[i + 1] == ObjectB)
        ; // Your code
0

IEnumerable - iterator forward-only. IEnumerator interface, :

IEnumerable .

bool MoveNext()
void Reset()
object Current

, , reset . .

IEnumerable

bool someFlag = false;
IEnumerable<object> collection = new object[]{"string", true, 4, DateTime.Now};
using (var enumerator = collection.GetEnumerator()) {
  while (true ) {
   bool end = enumerator.MoveNext();
   if (!end) {
      if (enumerator.Current.GetType() == typeof(string)) {
        end = enumerator.MoveNext();
        if (!end && enumerator.Current.GetType() == typeof(bool))
          someFlag = true;
      }
   } 
   if (end) break;
  }
}

bool someFlag = false;
List<object> collection = new object[]{"string", true, 4, DateTime.Now};
int i = 0;
while (true ) {
   bool end = i < collection.Count;
   if (!end) {
      if (collection[i] == typeof(string)) {
        i++;
        end = i < collection.Count;
        if (!end && collection[i] == typeof(bool))
          someFlag = true;
      }
   } 
   if (end) break;
  }
}
0
source

Using my answer to this question , I chose this option as a possible solution. This will work for any type of collection; even those that cannot be indexed.

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());
    }
}

And here is the corresponding code.

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();
        }
    }
}
0
source

Source: https://habr.com/ru/post/1756098/


All Articles