List 使用模式匹配操作列表

List 使用模式匹配操作列表,list,haskell,pattern-matching,List,Haskell,Pattern Matching,我想写一个函数,它以一个列表作为输入值,并通过以下方式对其进行操作: 步骤1:将列表中的每3个元素放入子列表中。 如果剩下的元素少于3个,那么剩下的元素将放在一个特定的子列表中,该子列表在步骤2中不相关 步骤2:颠倒所创建子列表中元素的顺序。 第一个元件应置于第三个元件的位置,第二个元件应置于第一个元件的位置,第三个元件应置于第二个元件的位置。([1,2,3]转化为[2,3,1]) 例如: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] -- shou

我想写一个函数,它以一个列表作为输入值,并通过以下方式对其进行操作:

步骤1:将列表中的每3个元素放入子列表中。 如果剩下的元素少于3个,那么剩下的元素将放在一个特定的子列表中,该子列表在步骤2中不相关

步骤2:颠倒所创建子列表中元素的顺序。 第一个元件应置于第三个元件的位置,第二个元件应置于第一个元件的位置,第三个元件应置于第二个元件的位置。([1,2,3]转化为[2,3,1])

例如:

[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] 

-- should be transformed to 
[[2,3,1],[5,6,4],[8,9,7],[11,12,10],[14,15,13],[16,17]] 
到目前为止,我发现以下方法可以将每3个元素放在子列表中,但我不太确定如何更改每个子列表中元素的顺序以满足需求

    splitEvery :: Int -> [a] -> [[a]]
    splitEvery _ [] = []
    splitEvery n xs = as : splitEvery n bs 
        where (as,bs) = splitAt n xs

如果内部列表始终为3个元素,则可以对该事实进行硬编码,并使用以下简单解决方案:

f :: [a] -> [[a]]
f [] = []
f (x1:x2:x3:xs) = [x2,x3,x1]:f xs
f xs = [xs]

你也可以通过取舍来实现你的目标

f [] = []
f xs = (take 3 xs) : f2 (drop 3 xs)

惯用的Haskell比这里的其他答案要好得多。基本上,总是尝试设计API,使其包含不会发生死角的证据。对列表进行硬编码文字或硬编码翻转操作(不保证其长度)总是不好的

{-#语言LambdaCase}
除法:[a]->[a](a,a,a)]
divide=\case
[]          -> []
t1:t2:t3:ts->右(t1,t2,t3):划分ts
ts->[左ts]
流程::[a](a,a,a)]->[a]]
过程=fmap(展平.翻转),其中
flipEls=fmap$\(t1、t2、t3)->[t2、t1、t3]
展平=任一id

现在,您可以像
过程一样进行操作。divide

您可以使用一个单独的函数来反转长度为3的列表中的元素。它将简单地返回任何其他列表的列表而不做任何修改。
[1,2,3]
[2,3,1]
是一个旋转,而不是反转(这将是
[3,2,1]
)。这只解决了步骤1。您甚至测试过这个吗?它充满了错误。1.语法错误:
而不是
除法之后。2.使用
\case
时不启用lambdase扩展。3.您可以使用第三方库中的
mapRight
,这一点您不必提及。4. <代码>进程
不会进行类型检查(你正在呼叫
concat
,不应该这样)。@JosephSible,事实上不是,我是在等火车的电话上写的。感谢您捕获
而不是
和不必要的
concat
。其余的(lambdacase和mapRight)很容易被谷歌搜索到。