如何在Haskell中的字符串列表中更改Char

时间:2013-11-15 22:15:06

标签: string list haskell

我刚刚解决了一个问题,涉及使用字符串在某个位置更改某个字符:

changeStr :: Int -> Char -> String -> String
changeStr x char zs = take (x-1) zs ++ [char] ++ drop x zs

- 此函数接受int输入,char和字符串,然后将int位置的字符串更改为指定的char。它通过将字符串分成三部分来完成此操作,第一部分是指定位置之前的所有字符串,第二部分是指定位置,第三部分是指定位置之后的所有字符串。然后将第二部分更改为指定的字符,并将所有内容连接在一起。

{-

Cw2013> changeStr 2 'i' "dog"
"dig"

-}

现在我基本上尝试做类似于第一个问题的事情,但是通过使用函数changeStr作为辅助函数来使用字符串列表来完成它但我似乎感到困惑。我似乎无法解决它。以下是我在下面所做的事情:

changeRaw :: (Int,Int) -> Char ->  [String]-> [String]
changeRaw x y char zs = (take (y-1) zs) ++ (changeStr x char (head (take (y-1))) ++ (drop y zs)

有关我做错的任何建议吗?

3 个答案:

答案 0 :(得分:1)

您问题的直接解决方法是(head (take (y-1)))应该是(head (drop (y-1) zs))。稍微更好的替换是使用(zs !! (y-1)),因为(!!)是标准(从零开始)的Haskell列表索引操作。

另请注意,类型签名(Int,Int) -> Char -> [String]-> [String]与您的功能模式changeRaw x y char zs不匹配。


但是,更多Haskellish解决方案会更简单,更通用:

-- generalized helper function
mapElt :: Int -> (a -> a) -> [a] -> [a]
mapElt n f xs = take (n-1) xs ++ f (xs!!(n-1)) : drop n xs

-- generic replacement for changeStr
setElt :: Int -> a -> [a] -> [a]
setElt n e xs = mapElt n (const e) xs

-- generic replacement for changeRaw
setElt2 :: Int -> Int -> a -> [[a]] -> [[a]]
setElt2 x y e xss = mapElt y (setElt x e) xss

剩下的烦恼包括基于单一的索引,以及mapElt实现中仍然不优雅的索引机制。

[更新以反映已编辑的问题]

答案 1 :(得分:1)

您没有changeStr的一般解决方案。

你可以做得更优雅:

changeNLst :: Int -> a -> [a] -> [a]

你有很重的解决方案。

1)您可以将[char] ++ drop x zs替换为char : drop x zs

2)你可以使用splitAt :: Int -> [a] -> ([a], [a])

changeStr x char zs = before ++ (char : tail after)
    where (before, after) = splitAt (x-1) zs

答案 2 :(得分:0)

中间位

changeStr x char (head (take (y-1))

缺少任何您想要take的列表的提及。