我刚刚解决了一个问题,涉及使用字符串在某个位置更改某个字符:
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)
有关我做错的任何建议吗?
答案 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
的列表的提及。