2009-06-24 31 views
6

我正在通过Learn You a Haskell阅读,并且我试图将列表中的元素移动到头部。我想出了我认为是天真的方式,我很好奇,如果有人能告诉我经验丰富的Haskell程序员会做什么。如何在Haskell中移动列表中的元素?

在这个例子中,我有一个整数列表,我想将元素'4',它将索引'3',到列表的头部。

let nums = [1, 2, 3, 4, 5] 
(nums !! 3) : delete (nums !! 3) nums 

返回[4,1,2,3,5]。

您认为如何?

+3

“删除”

toHead n xs = x : pre ++ post where (pre, x:post) = splitAt n xs 

删除给定元素的第一次出现,所以如果有可能删除错误的元素重复... – sth 2009-06-24 23:25:44

回答

15

我会做这种方式:

move n as = head ts : (hs ++ tail ts) 
    where (hs, ts) = splitAt n as 

splitAt在给定的位置分割的列表,它返回由分裂(这里hsts)创建的两个部分。应该移动到前面的元素现在在ts的开头。 head ts只返回ts的这第一个元素,tail ts返回所有内容但是表示第一个元素。函数的结果只是这些部分以正确的顺序组合在一起:hstail ts级联,并由元素head ts作为前缀。

+3

toHead n l = let(xs,y:ys)= splitAt n l in y:xs ++ ys – Stephan202 2009-06-24 23:24:43

+0

......请问您能否描述一下请理解代码? – shahkalpesh 2009-06-24 23:31:01

0

什么是共同发病?
几天前我在读相同的东西。再看一遍&写下如下。

nums !! 3 : [x | x <- nums, (x == (num !! 3)) == False] 
+0

两个问题:首先,重复的元素被删除。其次(较少的问题),不等于运算符是(/ =),而不是((a == b)== False)。 – 2009-06-24 23:25:14

+0

好抓。正如你所看到的,我是一个初学者。谢谢纠正:) – shahkalpesh 2009-06-24 23:28:46

11

有经验的Haskellers很少使用列表索引。我会用突破来避免重复遍历(假设你想匹配的元素“4”,而不是指数“3”):

case break (== 4) [1, 2, 3, 4, 5] of 
    (a,x:xs) -> x:a ++ xs 
    (a,xs) -> a ++ xs 

如:

Prelude Data.List> case break (== 4) [1, 2, 3, 4, 5] of (a,x:xs) -> x:a ++ xs; (a,xs) -> a ++ xs 
[4,1,2,3,5] 

我们可以做同样的通过 'splitAt' 索引:

Prelude Data.List> case splitAt 3 [1, 2, 3, 4, 5] of (a,x:xs) -> x:a ++ xs; (a,xs) -> a ++ xs 
[4,1,2,3,5] 
+0

是的,它与元素4不匹配索引'3'。对不起,混淆 – afrosteve 2009-06-25 04:32:38

3

还有

toHead n l = l !! n : take n l ++ drop (n+1) l 

这可能比使用splitAt稍微容易一些。

8

对某事的解决方案小的修改:使用模式的匹配,而不是headňtail

相关问题