1

I am trying to port some code from Python to C#.

The goal is to compare adjacent elements and see if four consecutive values are bigger than one another.

Following this post (Compare two adjacent elements in same list) I was able to use pairwise on a deque to succesfully compare adjacent elements.

//In python
from more_itertools import pairwise

for x, y in pairwise(a_deque):
    if (x < y):
        i += 1
        if (i == 4)
            print("Hello world!")

The problem is that C# does not contain the more_itertools library so I am currently looking for a similar technique to achieve the same solution.

FYI. The deque implementation is from https://www.nuget.org/packages/Nito.Collections.Deque/

Any suggestions?

XOR
  • 407
  • 6
  • 16

4 Answers4

1

You can implement the python pairwise method yourself like this:

public static IEnumerable<(T, T)> Pairwise<T>(IEnumerable<T> collection)
{
    using (var enumerator = collection.GetEnumerator())
    {
        enumerator.MoveNext();
        var previous = enumerator.Current;
        while (enumerator.MoveNext())
        {
            yield return (previous, enumerator.Current);
            previous = enumerator.Current;
        }
    }
}

Then the algorithm in c# is structural very similar to the python version:

static void Main(string[] args)
{
    var values = new[] { 5, 7, 8, 9, 10, 10, 8, 2, 1 };

    var i = 0;

    foreach (var (x, y) in Pairwise(values))
    {
        if (x < y)
        {
            i++;
            if (i == 4)
                Console.WriteLine("Hello world!");
        }
    }

    Console.ReadLine();
}
Mario Dekena
  • 843
  • 6
  • 20
1

Just create the function:

static IEnumerable<(T, T)> PairWise<T>(IEnumerable<T> collection)
{
    var queue = new Queue<T>();

    foreach (T item in collection)
    {
        queue.Enqueue(item);

        if (queue.Count == 2)
        {
            T x = queue.Dequeue();
            T y = queue.Peek();
            yield return (x, y);
        }
    }
}

and use it:

foreach ((int x, int y) in PairWise(new[] {1, 2, 3, 4, 5}))
{
    Console.WriteLine($"{x} {y}");
}
NightmareZ
  • 41
  • 5
1

There is a project called MoreLINQ with clever LINQ extensions. Most of the time though the code is really simple thanks to LINQ's simplicity. You can add it as a NuGet package or as individual source packages that add just the operators you want.

Pairwise.cs implements an operator that can apply a function to pairs of elements :

int[] numbers = { 123, 456, 789 };
var result = numbers.Pairwise((a, b) => a + b);

The source is really simple - retrieve an item and if we haven't reached the end, retrieve another one and apply the function :

    public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> resultSelector)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector));

        return _(); 

        IEnumerable<TResult> _()
        {
            using (var e = source.GetEnumerator())
            {
                if (!e.MoveNext())
                    yield break;

                var previous = e.Current;
                while (e.MoveNext())
                {
                    yield return resultSelector(previous, e.Current);
                    previous = e.Current;
                }
            }
        }
    }

The only "trick" is the use of the local iterator function named ... _

You can thing of the Pairwise operator as an optimized Window operator for just 2 items. There's another Window operator that can return sequences of N items.

This expression :

var x=Enumerable.Range(1,5).Window(3);

Produces the following arrays :

{1,2,3}
{2,3,4}
{3,4,5}
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
-1

You could try like this:

for (int i = 0; i < arr.Length - 1; ++i)
{
    int a = arr[i];
    int b = arr[i + 1];
    Console.WriteLine($"{a} {b}");
}
Manjar
  • 3,159
  • 32
  • 44
NightmareZ
  • 41
  • 5