我写了一个函数来计算列表的中值
task3 xs | null xs = Nothing
| odd len = xs !! mid
| even len = evenMedian
where len = length xs
mid = len `div` 2
evenMedian = (xs !! mid + xs !! (mid+1)) / 2
我认为这是正确的,它也通过了负载。但是当我使用该功能时,它不起作用。 这有什么不对?
答案 0 :(得分:4)
正如李提到的那样,必须首先对列表进行排序。 ([1,1,8,1,1]的中位数是1(不是8)。所以你必须将它排序为[1,1,1,1,8]然后取中间的那个)。
另一件事是,您返回Nothing
,因此其他结果也必须是Maybe a
类型:
Just $ xs !! mid
Just evenMedian
您可以使用sort
中的Data.List
对列表进行排序,然后再将其应用于task3。
像这样:
task xs = task3 (sort xs)
答案 1 :(得分:2)
这是一个Haskell实现:
import Data.List
median :: Ord a => [a] -> a
median xs = select (length xs `div` 2) xs
select :: Ord a => Int -> [a] -> a
select i xs
| n <= 5
= sort xs !! i
| lengthLower == i
= medianOfMedians
| lengthLower < i
= select (i - lengthLower - 1) upperPartition
| otherwise
= select i lowerPartition
where
n = length xs
medianOfMedians = median (map median (chunksOf 5 xs))
(lowerPartition, _:upperPartition) = partition (< medianOfMedians) xs
lengthLower = length lowerPartition
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs
| (beginning, rest) <- splitAt n xs
= beginning : chunksOf n rest
答案 2 :(得分:1)
即使有了kaan的答案,这段代码仍然无法产生正确的中位数。另一个被忽略的问题是Haskell列表是零索引的。因此,除了
之外,所有代码都是正确的evenMedian = (xs !! mid + xs !! (mid+1)) / 2
实际应该是
evenMedian = (xs !! (mid - 1) + xs !! mid) / 2
否则结果不正确。错误的方法产生task3 [1,2,3,4] ==只需3.5,而正确的方法产生task3 [1,2,3,4] ==只需2.5
答案 3 :(得分:1)
递归也可以做。
import Data.List
medianFromSorted :: Fractional a => [a] -> Maybe a
medianFromSorted [] = Nothing
medianFromSorted [a] = Just a
medianFromSorted [a,b] = Just ((a + b) / 2)
medianFromSorted (a:xs) = medianFromSorted (init xs) -- init is not efficient
median :: Ord a => Fractional a => [a] -> Maybe a
median = medianFromSorted . sort
答案 4 :(得分:0)
我的median
for Integer版本
import Data.List (sort)
getMiddle [] = 0
getMiddle xs = (a' + b') `div` 2
where a' = head $ drop a xs
b' = head $ drop b xs
a = (n `div` 2)
b = n' - 1
n' = n `div` 2
n = length xs
median :: [Integer] -> Integer
median [] = 0
median xs = result
where result = if (n `mod` 2 == 0)
then getMiddle sorted
else head $ drop a sorted
a = (n - 1) `div` 2
n = length xs
sorted = sort xs
main = print $ median [1, 4, 5, 7, 9, 100]
-- 6