リスト要素間の「不一致を測定する」とはどういう意味かわかりませんが、リスト内の「最大の」要素を計算する場合は、組み込みmaximum
関数を使用します。
maximum :: Ord a => [a] -> a
この関数は、順序付け可能な値のリストを取得するため、すべての数値、文字、および文字列が含まれます。
最大値と最小値の差を取得したい場合は、同様の関数を使用してminimum
、2 つを減算するだけです。確かに、リストを 1 回だけトラバースするか、リストを並べ替えてから最初と最後の要素を取得するという、わずかに高速な解決策があるかもしれませんが、ほとんどの場合、それdiff xs = maximum xs - minimum xs
は十分に高速であり、他の人にとって最も理にかなっています。
したがって、やりたいことは、各要素の最小値と最大値を計算するのではなく、連続する要素間の差を計算することです。直接インデックスを作成する必要はありませんが、 という便利な関数を使用してzipWith
ください。二項演算と 2 つのリストを取り、その二項演算を使用してそれらをまとめて「圧縮」します。だから何か
zipWith (+) [1, 2, 3] [4, 5, 6] = [1 + 4, 2 + 5, 3 + 6] = [5, 7, 9]
リストの 1 つが早く使い果たされた場合、そこで停止するため、かなり便利です。だからあなたは次のようなことができます
diff xs = zipWith (-) xs ???
しかし、リストを 1 オフセットするにはどうすればよいでしょうか。簡単な (そして安全な) 方法は、 を使用することdrop 1
です。を使用することもできますが、 が空のリストのtail
場合はエラーがスローされ、プログラムがクラッシュしますが、そうではありませんxs
drop
diff xs = zipWith (-) xs $ drop 1 xs
したがって、例は次のようになります
diff [1, 2, 3, 4] = zipWith (-) [1, 2, 3, 4] $ drop 1 [1, 2, 3, 4]
= zipWith (-) [1, 2, 3, 4] [2, 3, 4]
= [1 - 2, 2 - 3, 3 - 4]
= [-1, -1, -1]
この関数は正と負の値を返します。必要なのは大きさだけなので、次のabs
関数を使用できます。
maxDiff xs = ??? $ map abs $ diff xs
そして、上で強調した関数を使用します。
maxDiff xs = maximum $ map abs $ diff xs
そして、あなたは完了です!派手になりたい場合は、これをポイントフリー表記で次のように書くこともできます。
maxDiff = maximum . map abs . diff
さて、これは実際にはエラーをスローするため、空のリストでmaximum []
エラーを発生させますが、それを解決する方法を見つけさせます.