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(请注意,a = (->)为简单起见,我在该类型签名中进行了替换)干净地执行decorate-sort-undecorate transform

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。正常的做法是返回 a Maybe a,其中Nothing指示错误(在本例中为空列表)并Just a表示“真实”返回值。例如

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

这要好得多,因为从代码安全的角度来看,部分函数(对于某些输入值未定义的函数)是可怕的。您可以Maybe使用模式匹配(在Nothingand上匹配)和(preferable 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

我将尝试简短地解释这段代码在做什么。您需要找到列表中最频繁出现的元素,因此首先想到的想法是找到所有元素的频率。Nowgroup是一个组合相邻相似元素的函数。

> 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两次时间即可获得频率最高的元素。

于 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 回答