Haskell选择第k个元素

时间:2012-12-07 04:02:43

标签: haskell

想要从列表中选择第k个元素,可以像这样调用函数

selectN 5 aList

和我的功能

selectN :: Int -> a -> a
selectN 1 (x:_) = x
selectN [] _     = error "Index out of bounds"
selectN k (_:xs) 
  | n < 1           = error "Index out of bounds"
  | otherwise       = selectN xs (n - 1)

2 个答案:

答案 0 :(得分:3)

好的,所以你的代码存在一些问题,所以首先让我们解决一下问题:

selectN :: Int -> a -> a --You take in a list of a ie [a] and return a. So this is bit off
selectN 1 (x:_) = x 
selectN [] _     = error "Index out of bounds" -- Fine but not strictly needed
selectN k (_:xs) 
  | n < 1           = error "Index out of bounds" 
  | otherwise       = selectN xs (n - 1) --You've got the params backwards here.

所以要解决这个问题,首先要找一个好的签名:

selectN :: Int -> [a] -> a

现在基本情况:

selectN 1 (x:_) = x --I would suggest using 0 not 1. 
                    --Most things in Haskell are 0 based.
selectN n (x:xs) = selectN (n-1) xs

这样可行,没有有用的错误消息,但您可以弄清楚如何添加这些消息。

使用类型签名为

(!!)也可以轻松完成此操作
(!!) :: [a]->Int->a

所以

selectN = flip (!!)

查看hoogle这对这类事情有用。

答案 1 :(得分:1)

要选择列表的第k个元素,请使用!!。第一个元素是索引0

selectN = (!!)

ghci> let test = "abracadabra"
ghci> test !! 0   
ghci> 'a'
ghci> test !! 9
ghci> 'r'

但请注意indexOutOfRange例外

ghci> test !! 11 
*** Exception: Prelude.(!!): index too large

版本:使功能安全

可以编写safeSelectN来处理错误异常,并允许程序在没有任何IO操作的情况下安全地继续。要做到这一点,需要进行以下修改

safeSelectN :: Int -> [a] -> [a]
safeSelectN n xs = if null xs || length xs < n then [] else [xs !! n]

在这种情况下,将通过接收空列表来检测错误。

ghci> safeSelectN 3 ""
[]
ghci> safeSelectN 0 ""
[]
ghci> safeSelectN 3 "abcd" --like this
['d']

因此,当结果正确时,您不会仅使用第k个元素,而是使用仅包含第k个元素的列表。