我正在尝试编写一个函数,将字符串中的单个字符添加到字符串列表中,例如
combine ", !" ["Hello", "", "..."] = ["Hello,", " ", "...!"]
我试过这个:
combine :: String -> [String] -> [String]
combine (y:ys) (x:xs) =
[x:y, combine ys xs]
答案 0 :(得分:2)
如果要逐个元素地组合列表,通常是您正在查看的zip
。在这种情况下,您确切地知道如何组合元素 - 这使它成为zipWith
。
zipWith
采用“组合函数”,然后创建一个使用所述组合函数组合两个列表的函数。让我们调用你的“组合”函数append
,因为它会在字符串的末尾添加一个字符。您可以这样定义:
append char string = string ++ [char]
你看到它是如何工作的吗?例如,
append 'e' "nic" = "nice"
或
append '!' "Hello" = "Hello!"
现在我们知道了,回想一下zipWith
采用“组合函数”,然后创建一个使用该函数组合两个列表的函数。因此,您的功能可以轻松实现为
combine = zipWith append
并且在您提供的列表中按顺序对每个元素执行append
,如下所示:
combine ", !" ["Hello", "", "..."] = ["Hello,", " ", "...!"]
答案 1 :(得分:2)
一个简单的就是
combine :: [Char] -> [String] -> [String]
combine [] _ = []
combine _ [] = []
combine (c:cs) (x:xs) = x ++ [c] : combine cs xs
甚至更简单地使用zipWith
combine :: [Char] -> [String] -> [String]
combine = zipWith (\c x -> x ++ [c])
我必须做一些额外的工作才能让它发挥作用。我会为你分解它。
首先,我将函数的类型指定为[Char] -> [String] -> [String]
。我可以使用String
作为第一个参数,但是你在概念上操作的是字符列表和字符串列表,而不是字符串和字符串列表。
接下来,我必须为此函数指定边缘情况。当任一参数为空列表[]
时会发生什么?简单的答案就是结束计算,所以我们可以编写
combine [] _ = []
combine _ [] = []
此处_
匹配任何内容,但将其丢弃,因为它未在返回值中使用。
接下来,对于函数的实际主体我们想要获取第一个字符和第一个字符串,然后将该字符附加到字符串的末尾:
combine (c:cs) (x:xs) = x ++ [c]
但是这对cs
或xs
,我们列表的其余部分没有任何作用(甚至不会使用上面的类型签名进行编译)。我们需要继续前进,因为我们正在生成一个列表,所以通常使用前置运算符:
combine (c:cs) (x:xs) = x ++ [c] : combine cs xs
然而,这是一种常见的模式,有一个名为zipWith
的辅助函数可以为我们处理边缘情况。它的类型签名是
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
它同时向下走两个输入列表,将相应的元素传递给提供的函数。由于我们要应用的函数是\c x -> x ++ [c]
(变成lambda函数),我们可以将它放到zipWith
作为
combine cs xs = zipWith (\c x -> x ++ [c]) cs xs
但是Haskell会让我们在可能的情况下放弃参数,所以我们可以将其减少到
combine :: [Char] -> [String] -> [String]
combine = zipWith (\c x -> x ++ [c])
就是这样!
答案 2 :(得分:0)
你很亲密。你有什么问题。
y的类型为Char,x的类型为String,它是[Char]的别名。这意味着您可以使用y:x将y添加到列表顶部,但不能使用相同的:
运算符将y添加到列表的末尾。相反,您将y放入列表并加入列表。
x ++ [y]
还必须有一个基本案例,否则这个递归将继续,直到它在列表和崩溃中都没有元素。在这种情况下,我们可能没有任何想要添加的内容。
combine [] [] = []
最后,一旦我们创建了元素y ++ [x]
,我们就想将它添加到我们计算的其余项目的顶部。因此,我们使用:
将其列入我们的列表。
combine :: String -> [String] -> [String]
combine [] [] = []
combine (x : xs) (y : ys) = (y ++ [x]) : (combine xs ys)
关于此代码的一个注意事项,如果您的字符串中的字符数与列表中的字符串数不同,那么这将会崩溃。你可以通过多种方式处理这种情况,bheklilr的答案解决了这个问题。
kqr的答案也很有效,可能是在实践中最好的答案。