我正在阅读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]。
您怎么看?
答案 0 :(得分:15)
我会这样做:
move n as = head ts : (hs ++ tail ts)
where (hs, ts) = splitAt n as
splitAt
在给定位置拆分列表,它返回由拆分创建的两个部分(此处为hs
和ts
)。应该移到前面的元素现在位于ts
的开头。 head ts
只返回ts
的第一个元素,tail ts
返回但的第一个元素。函数的结果只是按正确的顺序组合这些部分:hs
与tail 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)
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]