【问题标题】:Drop nth Element from list从列表中删除第 n 个元素
【发布时间】:2013-04-27 16:34:51
【问题描述】:

我已经自学了一个月左右的 Haskell,今天我正在阅读第 16 个问题的解决方案并提出了一个问题。

这是一个链接:http://www.haskell.org/haskellwiki/99_questions/Solutions/16

基本上,这个问题要求创建一个函数,从列表中删除每个第 N 个元素。 例如,

*Main> dropEvery "abcdefghik" 3

"abdeghk"

链接中的第一个解决方案是

dropEvery :: [a] -> Int -> [a]
dropEvery [] _ = []
dropEvery (x:xs) n = dropEvery' (x:xs) n 1 
  where
       dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
       dropEvery' [] _ _ = []
       divides x y = y `mod` x == 0

我的问题是为什么 dropEvery 定义了空列表的情况,而 dropEvery' 可以处理空列表? 我认为dropEvery [] _ = []可以简单地去掉,修改一些其他的句子如下应该和上面的完全一样,看起来更短。

dropEvery :: [a] -> Int -> [a]
dropEvery xs n = dropEvery' xs n 1 
  where
       dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
       dropEvery' [] _ _ = []
       divides x y = y `mod` x == 0

谁能帮我解决这个问题?

【问题讨论】:

  • 注意这个函数的参数顺序是“错误的”;像这样的函数通常是Int -> [a] -> [a],这通常对管道情况更有用。为什么他们在那个例子中反其道而行之,我不知道。

标签: haskell


【解决方案1】:

我认为它们是相同的,作者可以按照您的建议简化代码。真是的,我用QuickCheck 尝试了这两个版本,它们似乎是一样的。


import Test.QuickCheck

dropEvery :: [a] -> Int -> [a]
dropEvery [] _ = []
dropEvery (x:xs) n = dropEvery' (x:xs) n 1 
  where
       dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
       dropEvery' [] _ _ = []
       divides x y = y `mod` x == 0

dropEvery2 :: [a] -> Int -> [a]
dropEvery2 xs n = dropEvery' xs n 1 
  where
       dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
       dropEvery' [] _ _ = []
       divides x y = y `mod` x == 0

theyAreSame xs n = (dropEvery xs n) == (dropEvery2 xs n)
propTheyAreSame xs n = n > 0 ==> theyAreSame xs n

在 ghci 中你可以做到

*Main> quickCheck propTheyAreSame 
+++ OK, passed 100 tests.

我还手动测试了一些角落案例

*Main> dropEvery [] 0
[]
*Main> dropEvery2 [] 0
[]
*Main> dropEvery [] undefined
[]
*Main> dropEvery2 [] undefined
[]

所以它们看起来是一样的。

所以我们的学习成果:

  1. Quickcheck 非常适合这类东西
  2. 不要低估自己。 :)

【讨论】:

  • 感谢您的回答!我很高兴听到我的猜测是正确的。我不知道快速检查。我需要能够使用 GHC 才能使用它吗?
  • @Tengu 你不使用 GHC 吗?您也可以使用runghcghci,但我确信QuickCheck 也可以在完全不同的编译器上工作。您可以在 Google 上搜索安装指南,但由于它是一个非常常见的库,因此应该很容易安装。
  • 我上个月刚开始使用 Haskell,从来没有使用过 GHC 编译器。 (实际上我什至不知道“编译器”是什么意思,尽管我的计算机科学专业的朋友为我解释了很多次哈哈)我会查找 QuickCheck 但我可能还没有为这些事情做好准备。谢谢你的回答!
  • @Tengu 哦,好吧。请以任何你觉得舒服的速度学习,随着时间的推移你的知识会成熟,你会以自然的方式探索更多的编程。在不相关的说明中:如果您发现我的回答有用,请考虑接受它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多