Haskell:计算列表中值的函数

时间:2014-01-25 15:10:33

标签: haskell

我写了一个函数来计算列表的中值

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

我认为这是正确的,它也通过了负载。但是当我使用该功能时,它不起作用。 这有什么不对?

5 个答案:

答案 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)

Median of Medians怎么样?

这是一个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