ここにいくつかの提案があります
del
独自の再帰を記述するのではなく、フィルタを使用して実装できます。あなたの定義には間違いがありました。削除中ys
ではなく、与える必要がありました。y
del x = filter (/=x)
obj
del
フィルタ機能が異なる場合と同様です。ys
同様に、ここでは定義ではなくy
、与える必要がありますobj
。
obj x = filter (==x)
tam
ただのlength
機能です
-- tam = length
n1
とのリストを保持する必要はありませんn
。また、アルゴリズムを変更していませんが、コードを読みやすくしました。
fun n1 n [] =n1
fun n1 n xs@(x:s) | length (obj x xs) > n = fun x (length $ obj x xs) (del x xs)
| otherwise = fun n1 n $ del x xs
rep xs@(x:s) = fun x (length $ obj x xs) (del x xs)
別の方法は、あまり最適ではありませんが、はるかに読みやすいです
import Data.List
import Data.Ord
rep :: Ord a => [a] -> a
rep = head . head . sortBy (flip $ comparing length) . group . sort
このコードが何をしているのかを簡単に説明しようと思います。リストの中で最も頻度の高い要素を見つける必要があるため、頭に浮かぶ最初のアイデアは、すべての要素の頻度を見つけることです。今group
は隣接する類似要素を組み合わせる機能です。
> group [1,2,2,3,3,3,1,2,4]
[[1],[2,2],[3,3,3],[1],[2],[4]]
したがって、並べ替えを使用して、同じ要素を互いに隣接させました
> sort [1,2,2,3,3,3,1,2,4]
[1,1,2,2,2,3,3,3,4]
> group . sort $ [1,2,2,3,3,3,1,2,4]
[[1,1],[2,2,2],[3,3,3],[4]]
最大頻度の要素を見つけることは、最大数の要素を持つサブリストを見つけることになります。sortBy
与えられた比較関数に基づいてソートできる関数がここにあります。したがって、基本的にlength
はサブリストを並べ替えました(反転は、並べ替えを昇順ではなく降順にするためです)。
> sortBy (flip $ comparing length) . group . sort $ [1,2,2,3,3,3,1,2,4]
[[2,2,2],[3,3,3],[1,1],[4]]
head
これで、頻度が最大の要素を取得するのに 2 回かかるだけです。