-5

想从列表中选择第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)
4

2 回答 2

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它对这类事情很有用。

于 2012-12-07T04:39:51.230 回答
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 个元素的列表。

于 2012-12-08T03:26:36.460 回答