Search through an array for two values ​​of the next o each other

I am working on a solution to a problem I solved in C #, but now I am porting my code to F #. I have a byte array and I need to find two values ​​(x, y) in this array. When I find it x

, it needs to be checked: if it y

is in the next index, we have a match. And if y

it is not in the next index, the search will continue. How can I solve this problem? I tried to use Array.findIndex

but without success because I don't know how to continue searching if y

not in the next index.

EDIT:

public void GetValue(byte[] data)
        {
            byte[] temp = new byte[4];
            for (int i = 0; i < data.Length; i++)
            {
                if (data[i] == Adress[0] && data[i + 1] == Adress[1])
                {
                    for (int j = 0; j < temp.Length; j++)
                    {
                        temp[j] = data[j + i + 2];
                    }
                    Value = BitConverter.ToInt32(temp, 0) * 0.01;
                    break;
                }

            }

      

+3


source to share


3 answers


You can easily do this in a function:



let bytes = [| 104uy; 101uy; 108uy; 108uy; 111uy |]

bytes 
|> Array.pairwise
|> Array.findIndex (fun x -> fst x = snd x)
//2

      

+10


source


You already have an accepted answer, but I was amazed by your comment "I'm amazed at how a clean solution can be in functional programming."

You could write your C # code too:

var index = Enumerable.Range(0, Int32.MaxValue)
                      .Zip(bytes.Zip(bytes.Skip(1)))
                      .Where(triplet => triplet.Item2.Item1 == triplet.Item2.Item2)
                      .Select(triplet => triplet.Item1)
                      .DefaultIfEmpty(-1)
                      .First();

      

If you take this a little, you can create multiple extension methods for IEnumerable<T>

:



public static class EnumerableExt
{
    public static IEnumerable<Tuple<A, A>> Pairwise<A>(this IEnumerable<A> self) =>
        self.Zip(self.Skip(1));

    public static int IndexOf<A>(this IEnumerable<A> self, Func<A, bool> f) =>
        Enumerable.Range(0, Int32.MaxValue)
                  .Zip(self)
                  .Where(x => f(x.Item2))
                  .Select(x => x.Item1)
                  .DefaultIfEmpty(-1)
                  .FirstOrDefault();

}

      

Which then will give you pretty much the same code as the version of F # you accepted:

var index = bytes.Pairwise()
                 .IndexOf(x => x.Item1 == x.Item2);

      

C # can be a very powerful functional language in its own right. If you have projects that mix C # and F # and you want your C # to look as good as your F, you can try my Functional Base Class Library for C # .

+3


source


Your C # code can be translated to F # like this (with better index checking so that you don't meet the dataset boundaries):

let getValue (a : _ []) (d : _ []) =
    let rec aux i =
        if i > data.Length - 6 then nan
        elif d.[i] = a.[0] && d.[i + 1] = a.[1] then
            0.01 * float (System.BitConverter.ToInt32 (d, i + 2))
        else aux (i + 1)
    aux 0

let value = getValue address data

      

But since reusing library functions can make the code easier to read compared to manual recursive loops, we can also use Array.pairwise

, as suggested:

let getValue2 (a : byte []) d =
    d |> Array.pairwise
      |> Array.tryFindIndex (fun (x, y) -> x = a.[0] && y = a.[1])
      |> Option.map (fun i ->
          0.01 * float (System.BitConverter.ToInt32 (d, i + 2)))
      |> function None -> nan | Some v -> v

      

+1


source







All Articles