如果我说我有两个字符串或字符列表,
list1 = ["c","a","t"]
list2 = ["d","o","g"]
如果我使用输入输出"ct"
读取字符串并将其传递给函数,则该函数应返回"dg"
。
请告诉我有关此类功能的任何想法。
答案 0 :(得分:5)
我会考虑使用这两个列表,将它们压缩在一起,使用Data.Map.fromList
创建一个查找Map,然后映射输入String并使用Map来计算替换它们的内容。
答案 1 :(得分:3)
我首先假设list1
和list2
有[Char]
类型(即String
),因为这就是您的文字似乎表明的内容(您的代码将其作为{ {1}} s - 如果你真的想要这个,请参阅附录中的通用版本。)
如果您[String]
这两个列表,最终会得到一对指示如何翻译字符的对。在您的示例中,zip
。我们将此称为查找列表。现在考虑函数lookup
:
zip list1 list2 = [('c','d'), ('a','o'), ('t','g')]
在我们的案例中,我们可以将其专门化为
lookup :: Eq a => a -> [(a, b)] -> Maybe b
所以我们有一些东西需要一个字符和一个查找列表,如果输入字符在查找列表中,则返回一个替换字符(否则为lookup :: Char -> [(Char, Char)] -> Maybe Char
)。现在我们只需要粘合我们一起找到的东西:我们基本上需要在输入字符串上映射Nothing
(更优雅地写为\c -> lookup c lookupList
),而抛出任意在查找列表中找不到的字符。好吧,输入mapMaybe
:
flip lookup
它完全符合我们的要求。现在你的函数可以写成
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
您需要导入replace :: String -> String -> String -> String
replace list1 list2 = mapMaybe ((flip lookup) (zip list1 list2))
。
附录,因为当您理解上述内容时:观察我们上面所做的与我们使用字符列表这一事实无关。我们可以使用任何类型的列表执行上述所有操作,其中等式是有意义的,即(列表)任何类型的Data.Maybe
类型类的实例(参见{{1的签名) 1}}以上)。而且,我们不必从该类型转换为自身 - 例如,上面的每个字符都可以发送一个整数!所以,我们可以写
Eq
现在只要lookup
是一个有平等意义的东西的列表,我们的函数就可以工作。替换字符只是一种特殊情况。
一个简单的例子:
replace :: (Eq a) => [a] -> [b] -> [a] -> [b]
replace list1 list2 = mapMaybe ((flip lookup) (zip list1 list2))
答案 2 :(得分:0)
对于两个字符串,您可以执行以下操作:
patt :: String -> String -> String -> String
patt (x : xs) (y : ys) p'@(p : ps)
| p == x = y : patt xs ys ps
| otherwise = patt xs ys p'
patt _ _ [] = []
main :: IO ()
main = do
putStrLn $ patt "cat" "dog" "ct"