我是Haskell的新手。我正在尝试使用递归来编写一个函数,给定两个列表(它们需要是相同的类型),交织它们的元素(在第一个和第二个列表之间交替使用元素)。当其中一个列表中没有其他元素时,它会停止,结果就是到目前为止所实现的列表。
interChange :: [a] -> [b] ->[(a,b)]
interChange _ [] = []
interChange [] _ = []
interChange (x:xs) (y:ys) = (x,y) : interChange xs ys
我的输出示例:
interChange [1,2,3] [4,5,6]
[(1,4),(2,5),(3,6)]
所需输出的示例是:
interChange [1,2,3] [4,5,6]
[1,4,2,5,3,6]
感谢您的帮助
答案 0 :(得分:3)
您的interleave :: [a] -> [a] -> [a]
与Prelude的source相同。
Bool
要编写您指定的函数,您实际上需要一对相同类型的列表。我们输出的是特定类型的列表,因此进入该列表的所有元素也必须具有该类型。
interleave = go True
where go _ [] ys = ys
go _ xs [] = xs
go True (x:xs) ys = x : go False xs ys
go False xs (y:ys) = y : go True xs ys
您可以通过传递go
以递归的方式实现此目的,指示您应该从哪个列表中获取下一个元素:
zip
评估[]
的最后两个子句之间的ping-pongs,直到其中一个输入列表为空,然后我们只返回另一个的其余部分。 (如果您希望它的行为更像xs
,则可以通过在这些情况下返回ys
而不是zip
或map (\(x, y) -> [x, y])
来截断输出。)
但我总是建议尽可能避免递归到更高级别的编程。我们可以将此函数编写为管道:
concat
interleave xs ys = concat $ map (\(x, y) -> [x, y]) $ zip xs ys
map
所以代码看起来像这样:
concat
我觉得这个代码比递归代码更容易理解,它需要你推理控制流 - 它只是一系列高级指令。
顺便提一下,您可以将中间版zip
拖入interleave xs ys = concatMap (\(x, y) -> [x, y]) $ zip xs ys
interleave xs ys = concat $ zipWith (\(x, y) -> [x, y]) xs ys
或SELECT
Student_Name AS StudentName,count(Student_Name) Total
FROM
Student_Table
GROUP BY
Student_Name`
:
{{1}}
答案 1 :(得分:2)
当使用两个非空列表interChange
和(x:xs)
调用(y:ys)
时,输出应该是以x
开头,然后是y
的列表,然后是更多东西。所以你应该写点像
interChange (x:xs) (y:ys) = x : y : ...