如何在Haskell中的列表中移动元素?

时间:2009-06-24 23:08:16

标签: list haskell

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

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

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

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

您怎么看?

5 个答案:

答案 0 :(得分: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加上前缀。

答案 1 :(得分:11)

经验丰富的Haskellers几乎没有使用列表索引。我会使用break来避免重复遍历(假设你想匹配元素'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]

答案 2 :(得分:8)

对ph解决方案的小修改:

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

使用模式匹配代替head n tail

答案 3 :(得分:3)

还有

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

可能比使用splitAt更容易理解。

答案 4 :(得分:0)

共同发病率是多少? 几天前我正在读相同的东西。再看一遍&写下来就像是。

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