【问题标题】:Swap characters between strings Haskell在 Haskell 字符串之间交换字符
【发布时间】:2012-02-28 18:34:58
【问题描述】:

如果我说我有两个字符串或字符列表,

list1 = ["c","a","t"]
 list2 = ["d","o","g"]

如果我使用输入输出"ct" 读取一个字符串并将其传递给函数,该函数应该返回"dg"

请告诉我有关此类功能的任何想法。

【问题讨论】:

    标签: string list haskell


    【解决方案1】:

    我会考虑获取这两个列表,将它们压缩在一起,使用Data.Map.fromList 创建一个查找映射,然后映射输入字符串并使用映射计算出替换它们的内容。

    【讨论】:

    【解决方案2】:

    我首先假设list1list2 具有[Char] 类型(即String),因为这就是您的文字似乎表明的内容(您的代码将它们作为[String]s - 如果您真的想要这个,见附录中的通用版本)。

    如果您zip 这两个列表,您最终会得到一个指示如何翻译字符的对列表。在您的示例中,zip list1 list2 = [('c','d'), ('a','o'), ('t','g')]。我们将把它称为我们的查找列表。现在考虑函数lookup

    lookup :: Eq a => a -> [(a, b)] -> Maybe b
    

    在我们的例子中,我们可以将其专门用于

    lookup :: Char -> [(Char, Char)] -> Maybe Char
    

    所以我们有一些东西,它接受一个字符和一个查找列表,如果输入字符在查找列表中,则返回一个替换字符(否则为Nothing)。现在我们只需要将我们找到的东西粘合在一起:我们基本上需要将\c -> lookup c lookupList(更优雅地写为flip lookup)映射到输入字符串,同时扔掉在输入字符串中找不到的任何字符查找列表。嗯,输入mapMaybe

    mapMaybe :: (a -> Maybe b) -> [a] -> [b]
    

    它完全符合我们的要求。现在你的函数可以写成

    replace :: String -> String -> String -> String
    replace list1 list2 = mapMaybe ((flip lookup) (zip list1 list2))
    

    您需要导入Data.Maybe

    附录,当您理解上述内容时:请注意我们上面所做的与我们使用字符列表这一事实无关。我们可以用 any 类型的列表来做上面的所有事情,这对相等是有意义的,即对于任何类型的(列表)是Eq 类型类的实例(参见上面lookup 的签名)。此外,我们不必从该类型转换为自身——例如,上面的每个字符都可以发送为一个整数!所以真的,我们可以写

    replace :: (Eq a) => [a] -> [b] -> [a] -> [b]
    replace list1 list2 = mapMaybe ((flip lookup) (zip list1 list2))
    

    现在只要list1 是一个对相等有意义的事物的列表,我们的函数就可以工作。替换字符只是一种特殊情况。

    一个简单的例子:

    > replace "cat" "dog" "ct"
    "dg"
    > replace "cat" [1,2,3] "ct"
    [1,3]
    

    【讨论】:

    • 哦,我明白了这个逻辑,如果你能提供更多,那将是一个巨大的帮助。
    • 因为我会从用户那里获取一个字符串的输入,然后用我自己的 [char] 列表转换字符串中的字符.. 类似于 Cesar 加密。
    • *** 表达式:替换 *** 预期类型:Eq a => [a] -> [b] -> [a] -> [c] *** 推断类型:Eq a => [a] -> [b] -> [a] -> [b]
    • 请注意,ivanm 的答案(使用Map)将比我的基于列表的解决方案执行得更好。我故意避免引入(更适合的)Map 数据结构以使其简单,但请记住 ivanm 的解决方案更好。
    • @user1194367:在这里工作正常...您是否尝试将replace 应用于某事?如果有,是什么?
    【解决方案3】:

    对于两个字符串,你可以这样做:

    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"
    

    【讨论】:

    • 这只会遍历替换列表一次,所以patt "cat" "dog" "ctc" 给出了一个不完整的模式匹配错误,而我认为它应该返回"dgd"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    相关资源
    最近更新 更多