2017-08-02 6 views
3

私はC#で解決した問題の解決に取り組んでいますが、今では私のコードをF#に移植しています。私はバイト配列を持っているので、この配列で2つの値(x、y)を検索する必要があります。 xが見つかったら、それをチェックする必要があります。yが次のインデックスにある場合は一致しています。 yが次の索引にない場合、検索は続行されます。この問題をどのように解決すればよいですか? yが次のインデックスにないときに検索を続行する方法がわからないので、私はArray.findIndexを使用しようとしましたが、成功しませんでした。配列を介して2つの値を次に検索する

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

完全な回答を書く時間がありませんが、['Seq.pairwise'](https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/seq.pairwise%5B% 27t%5D機能 - %5Bfシャープ%5D)機能。 'Array'モジュールには' Array.pairwise'という対応する関数がありますが、オンラインドキュメントはまだ更新されていません。これは配列 '[| 1; 2; 3; 4 |] 'を' [| (1,2); (2,3); (3,4)|] '。次に、 'findIndex'または' tryFindIndex'を実行して、新しく生成された配列のタプル内の2つの同一の数字がどこにあるかを調べることができます。 – rmunn

+0

あなたはC#コードを投稿することができますか? – s952163

+1

私はペアリングについて考えましたが、私の場合はこれがインデックス0と1にある場合にのみ正しいです。インデックス1のxsとインデックス2のyが一致すると一致しません。 –

答えて

10

あなたは簡単に関数にこれを行うことができます。

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

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

この解決策は私が望むものです。Imは、クリーンなソリューションが機能プログラミングでどのように機能するか驚いています –

+2

@MateuszAd - この回答が問題の解決に役立った場合は、スコアの下にあるチェックマークをクリックして受け入れたとマークする必要があります。それは、後で検索であなたの質問を見つける他の誰もがそれが正しく答えられたことを知っているので、彼らは同じ問題がある場合、彼らは答えを見つけることができるでしょう。 – rmunn

+3

'fst'と' snd'を使うのではなく、 'fun(x、y) - > x = y'という対を解体します。 –

1

次のように実行されませんので、あなたのC#コードは、より良いインデックスチェックして(F#2に変換することができデータ配列の境界を超えて):

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 

しかし、ライブラリ関数を再利用するとコードを読みやすくなります赤は、我々はまた、提案されているようArray.pairwiseを使用することができ、再帰的なループを手巻きします

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 
3

あなたはすでにあなたの受け入れ答えを持っているが、私はあなたのコメント「関数型プログラミングにすることができますどのようにきれいなソリューションびっくりイム」に打たれました。

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

をあなたは少しさらにあなたが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(); 

} 

、その後はほとんどあなたを与えるだろうあなたはどちらの機能もあなたのC#コードを記述することができ

受諾したF#バージョンとまったく同じコード:

C#はそれ自体が非常に強力な関数型言語になることができます。 C#とF#を混在させているプロジェクトがあり、C#をあなたのFと同じように見せたい場合は、my functional base class library for C#を試してみてください。

関連する問題