简体   繁体   English

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

[英]How to change a Char within a list of Strings in Haskell

I have just solved a question which involves changing a certain Char at a certain position with a String : 我刚刚解决了一个问题,涉及使用字符串在某个位置更改某个Char:

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

-- This function takes an int input, a char and a string and then changes the string at the int position to the specified char. - 此函数接受int输入,char和字符串,然后将int位置的字符串更改为指定的char。 It does this by splitting the string into three parts, the first part is all the string before the specified postion, the second is the specified position and the third is all the string after the specified position. 它通过将字符串分成三部分来完成此操作,第一部分是指定位置之前的所有字符串,第二部分是指定位置,第三部分是指定位置之后的所有字符串。 the second part is then changed to the specified character and everything is concatenated together. 然后将第二部分更改为指定的字符,并将所有内容连接在一起。

{-

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

-}

Now I am basically trying to do something similar to the first question but doing it with a list of Strings by using the function changeStr as an auxilory function but I seem to be getting confused. 现在我基本上尝试做类似于第一个问题的事情,但是通过使用函数changeStr作为辅助函数来使用字符串列表来完成它但我似乎感到困惑。 I cant seem to solve it. 我似乎无法解决它。 Here is what I have done below : 以下是我在下面所做的事情:

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)

Any suggestions on what I am doing wrong ? 对我做错了什么建议?

The immediate fix for your problem is that your (head (take (y-1))) should instead be (head (drop (y-1) zs)) . 你的问题的直接解决方案是你的(head (take (y-1)))应该是(head (drop (y-1) zs)) A slightly better substitution would be to use (zs !! (y-1)) , since (!!) is the standard (zero-based) Haskell list indexing operation. 稍微更好的替换是使用(zs !! (y-1)) ,因为(!!)是标准的(从零开始)Haskell列表索引操作。

Also, note that the type signature (Int,Int) -> Char -> [String]-> [String] does not match your function pattern changeRaw xy char zs . 另请注意,类型签名(Int,Int) -> Char -> [String]-> [String]与您的函数模式changeRaw xy char zs不匹配。


However, a more Haskellish solution would be simpler and more general: 但是,更多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

Remaining annoyances include the one-based indexing, and the still-inelegant indexing mechanic in the mapElt implementation. 剩下的烦恼包括基于单一的索引,以及mapElt实现中仍然不优雅的索引机制。

[updated to reflect edited question] [更新以反映编辑过的问题]

You have not general solution for changeStr . 您还没有针对changeStr一般解决方案。

You could do it more elegant: 你可以做得更优雅:

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

You have heavy solutions. 你有很重的解决方案。

1) You could replace [char] ++ drop x zs with char : drop x zs 1)你可以用char : drop x zs替换[char] ++ drop x zs char : drop x zs

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

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

The middle bit 中间位

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

is missing any mention of the list you want to take from. 缺少要在列表中没有提到take从。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM