5

リストの例で最も頻繁な値を取得するにはどうすればよいですか:

[1,3,4,5,6,6] -> output 6
[1,3,1,5] -> output 1

私は自分の機能でそれを取得しようとしていますが、達成できません。

私のコード:

del x [] = []
del x (y:ys) = if x /= y 
            then y:del x y 
            else del x ys



obj  x []= []
obj  x (y:ys) = if x== y then y:obj x y else(obj  x ys)

tam [] = 0
tam (x:y) = 1+tam  y

fun (n1:[]) (n:[]) [] =n1
fun (n1:[]) (n:[]) (x:s) =if (tam(obj x (x:s)))>n then fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s)) else(fun (n1:[]) (n:[]) (del x (x:s))) 

rep (x:s) = fun  (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s))
4

4 に答える 4

7

Satvik の最後の提案を拡張すると、(&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c'))from (簡単にするためにその型シグネチャControl.Arrowに置き換えたことに注意してください) を使用して、 decorate-sort-undecorate transformをきれいに実行できます。a = (->)

mostCommon list = fst . maximumBy (compare `on` snd) $ elemCount
      where elemCount = map (head &&& length) . group . sort $ list

head &&& length関数の型は[b] -> (b, Int)です。リストを最初の要素とその長さのタプルに変換するため、これを組み合わせるとgroup . sort、リスト内の個別の各値のリストと、それが発生した回数が得られます。


また、 を呼び出したときに何が起こるかを考える必要がありますmostCommon []。要素がまったくないため、明らかに意味のある値はありません。現状では、提案されたすべてのソリューション (私のものを含む) は空のリストで失敗するだけであり、これは適切な Haskell ではありません。通常行うべきことは、エラー (この場合は空のリスト) をMaybe a示し、「実際の」戻り値を表す を返すことです。例えばNothingJust a

mostCommon :: Ord a => [a] -> Maybe a
mostCommon [] = Nothing
mostCommon list = Just ... -- your implementation here

部分関数 (一部の入力値に対して定義されていない関数) は、コードの安全性の観点からは恐ろしいものであるため、これははるかに優れています。Maybeパターン マッチング (Nothingとでのマッチング) と (ではなくandが望ましいJust x) の関数を使用して、値を操作できます。Data.MaybefromMaybemaybefromJust

于 2012-12-12T11:44:25.073 に答える
6

あなたが達成したいことをするコードからいくつかのアイデアを得たい場合のために、ここに例があります:

import Data.List (nub, maximumBy)
import Data.Function (on)

mostCommonElem list = fst $ maximumBy (compare `on` snd) elemCounts where
    elemCounts = nub [(element, count) | element <- list, let count = length (filter (==element) list)]
于 2012-12-12T06:11:26.467 に答える
3

ここにいくつかの提案があります

del独自の再帰を記述するのではなく、フィルタを使用して実装できます。あなたの定義には間違いがありました。削除中ysではなく、与える必要がありました。y

del x = filter (/=x)

objdelフィルタ機能が異なる場合と同様です。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 回かかるだけです。

于 2012-12-12T06:07:08.537 に答える
0

argmaxすでに関数があるとしましょう。list-extras独自に作成することも、パッケージを再利用することもできます。とにかくパッケージをよく見てみることを強くお勧めします。

次に、それは非常に簡単です:

import Data.List.Extras.Argmax ( argmax )

-- >> mostFrequent [3,1,2,3,2,3]
-- 3
mostFrequent xs = argmax f xs
  where f x = length $ filter (==x) xs
于 2015-12-01T19:43:25.650 に答える