[英]How to change a Char within a list of Strings in Haskell
我剛剛解決了一個問題,涉及使用字符串在某個位置更改某個Char:
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)
對我做錯了什么建議?
你的問題的直接解決方案是你的(head (take (y-1)))
應該是(head (drop (y-1) zs))
。 稍微更好的替換是使用(zs !! (y-1))
,因為(!!)
是標准的(從零開始)Haskell列表索引操作。
另請注意,類型簽名(Int,Int) -> Char -> [String]-> [String]
與您的函數模式changeRaw xy 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
實現中仍然不優雅的索引機制。
[更新以反映編輯過的問題]
您還沒有針對changeStr
一般解決方案。
你可以做得更優雅:
changeNLst :: Int -> a -> [a] -> [a]
你有很重的解決方案。
1)你可以用char : drop x zs
替換[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
中間位
changeStr x char (head (take (y-1))
缺少要在列表中沒有提到take
從。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.