2016-10-20 77 views
0

リストの連続する要素の平均を計算する関数をOCamlに書き込もうとしています。たとえば、[1; 2; 3; 4]と入力すると、[1; 2; 3]が出力されます。 (1 + 2)/2とし、1とし、(2 + 3)/2をとり、2とするなどです。 私が書いたコードは、しかし、唯一の[1; 2]返しますOCamlの連続するリスト要素の平均計算

let rec average2 xs = match xs with 
|[] -> [] 
|x :: [] -> [x] 
|x :: x' :: xs -> if xs = [] then [(x + x')/2] else [(x + x')/2] @ (average2 xs) 

あなたはどのようにこの問題を解決する方法を教えてくださいすることができます。ありがとうございました。

答えて

1

あなたが試合でx :: y :: lを実行しているときは、効果的にリストの要素を永久に取り出しています。 ですから、要素のペアで操作を行いたい場合は、あなたが1人の背中を配置する必要があり

例:。

あなたは1と2を操作したい[1;2;3;4]

のリストを持っていますあなたは内の要素を追加することなく継続した場合、次の文は次のようになり

1 :: 2 :: [3;4] 

、あなたの試合ではと解釈されます

これはあなたが望むものではありません。

これを修正するには、(average2 (x'::xs)を実行する必要があります。(average2 xs)だけでなく、xsが要素を取り除いた残りのリストであるためです。

1

OCamlはp as valias patterns)を使用して変数vにパターンpをバインドすることができます:

上記
let rec average2 = function 
| x :: (y :: _ as tail) -> (x + y)/2 :: (average2 tail) 
| _ -> [] 

y :: _ as taily率いる非空のリストとしてtailと任意の尾を持つという名前のリストをdestructures _、その値は気にしません。 また、_が空であるかどうかをチェックしないように関数を単純化しました。再帰ではこれを処理します。 また、リストに0または1つの要素がある場合は、空のリストを返す必要があります。

# average2 [ 10; 20; 30; 40];; 
- : int list = [15; 25; 35]