如何在列表示例中获得最常见的值:
[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))
答案 0 :(得分:7)
扩展Satvik的最后一个建议,您可以使用(&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c'))
中的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。正常的做法是返回Maybe a
,其中Nothing
表示错误(在本例中为空列表),Just a
表示“实际”返回值。 e.g。
mostCommon :: Ord a => [a] -> Maybe a
mostCommon [] = Nothing
mostCommon list = Just ... -- your implementation here
这更好,因为从代码安全的角度来看,部分函数(某些输入值未定义的函数)非常糟糕。您可以使用模式匹配(Maybe
和Nothing
上的匹配)和Data.Maybe
中的函数(最好是Just x
和fromMaybe
来操纵maybe
值比fromJust
)。
答案 1 :(得分: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)]
答案 2 :(得分:3)
以下是一些建议
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来将彼此相邻的元素放在一起
> 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
,您可以根据给定的比较函数对其进行排序。所以基本上我已经对{1}}的子列表进行了排序(翻转只是为了使排序降序而不是升序)。
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]]
来获得频率最高的元素。
答案 3 :(得分: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