List 替换Haskell中字符串数组中的第n个字符
我是Haskell和函数式编程的新手。我正在尝试实现一个函数来获取这样的列表List 替换Haskell中字符串数组中的第n个字符,list,haskell,functional-programming,List,Haskell,Functional Programming,我是Haskell和函数式编程的新手。我正在尝试实现一个函数来获取这样的列表 ["abc", "def", "ghi"] 例如,希望能够替换yth元素中的第x个字符 replaceChar 1 2 'd' arr 会产生 ["abc", "ded", "ghi"] 所以本质上第一个参数是元素,第二个是字符串的位置,第三个是字符,最后一个是[string] 此函数的签名如下所示: replaceChar :: Int -> Int -> Char -> [String] -
["abc", "def", "ghi"]
例如,希望能够替换yth元素中的第x个字符
replaceChar 1 2 'd' arr
会产生
["abc", "ded", "ghi"]
所以本质上第一个参数是元素,第二个是字符串的位置,第三个是字符,最后一个是[string]
此函数的签名如下所示:
replaceChar :: Int -> Int -> Char -> [String] -> [String]
任何帮助都将不胜感激。谢谢 试试这个:
replace n 0 c (x:xs) = (replace' n c x) : xs
replace n m c (x:xs) = x : (replace n (m-1) c xs)
where
replace' 0 c (x:xs) = c : xs
replace' n c (x:xs) = x : (replace' (n-1) c xs)
在这里,您只需遍历列表,直到相应的索引为0
,然后替换匹配列表中的字符。我们使用相同的原则替换列表中的字符。我们遍历它,当我们到达指定的索引时,我们用新的字符替换该索引处的字符
最后,所有的东西都会互相消耗,以替换旧的结构,这次是替换字符。试试这个:
replace n 0 c (x:xs) = (replace' n c x) : xs
replace n m c (x:xs) = x : (replace n (m-1) c xs)
where
replace' 0 c (x:xs) = c : xs
replace' n c (x:xs) = x : (replace' (n-1) c xs)
在这里,您只需遍历列表,直到相应的索引为0
,然后替换匹配列表中的字符。我们使用相同的原则替换列表中的字符。我们遍历它,当我们到达指定的索引时,我们用新的字符替换该索引处的字符
最后,所有内容都会相互替换,以替换旧结构,这次是替换字符。让我们将此问题分解为两个函数,一个用于用新字符替换字符串中的元素,另一个用于替换字符串列表 我想推荐如下:
replaceCharInStr :: Int -> Char -> String -> String
replaceCharInStr 0 c (s:ss) = c:ss
replaceCharInStr n c (s:ss) = s : ???
replaceCharInStr n c [] = error "replaceCharInStr: Empty string"
这里我们说,如果n
为0,用c
忽略字符串的第一个元素,然后如果n
不是0并且列表至少有一个元素,则在某个元素前面加上该元素(练习留给读者。提示:递归),然后如果字符串为空,则引发错误。我要说的是,我并不特别喜欢这里使用的error
,最好返回字符串,或者我们可以说replaceCharInStr n c[]=[c]
。我们还可以将类型签名更改为replaceCharInStr::Int->a->[a]->[a]
,因为这不是字符串特有的
对于下一个函数,我们要做的是获取一个索引,并在该索引处应用一个函数。通常,此函数的类型为
applyAt :: Int -> (a -> a) -> [a] -> [a]
并且可以使用类似于
replaceCharInStr
applyAt :: Int -> (a -> a) -> [a] -> [a]
applyAt 0 f (x:xs) = f x : xs
applyAt n c (x:xs) = x : ???
applyAt n c [] = error "applyAt: Empty list"
事实上,这与replaceCharInStr
的形状完全相同,因此如果您实现了这一形状,那么您应该能够按照applyAt
实现replaceCharInStr
replaceCharInStr n c xs = applyAt n (\x -> c) xs
-- Or = applyAt n (const c) xs
然后您的replaceChar
函数可以实现为
replaceChar :: Int -> Int -> Char -> [String] -> [String]
replaceChar n m c strings = applyAt n (replaceCharInStr m c) strings
-- Or = applyAt n (applyAt m (const c)) strings
剩下的就是实现
applyAt
让我们将这个问题分解为两个函数,一个用新字符替换字符串中的元素,另一个用于字符串列表
我想推荐如下:
replaceCharInStr :: Int -> Char -> String -> String
replaceCharInStr 0 c (s:ss) = c:ss
replaceCharInStr n c (s:ss) = s : ???
replaceCharInStr n c [] = error "replaceCharInStr: Empty string"
这里我们说,如果n
为0,用c
忽略字符串的第一个元素,然后如果n
不是0并且列表至少有一个元素,则在某个元素前面加上该元素(练习留给读者。提示:递归),然后如果字符串为空,则引发错误。我要说的是,我并不特别喜欢这里使用的error
,最好返回字符串,或者我们可以说replaceCharInStr n c[]=[c]
。我们还可以将类型签名更改为replaceCharInStr::Int->a->[a]->[a]
,因为这不是字符串特有的
对于下一个函数,我们要做的是获取一个索引,并在该索引处应用一个函数。通常,此函数的类型为
applyAt :: Int -> (a -> a) -> [a] -> [a]
并且可以使用类似于
replaceCharInStr
applyAt :: Int -> (a -> a) -> [a] -> [a]
applyAt 0 f (x:xs) = f x : xs
applyAt n c (x:xs) = x : ???
applyAt n c [] = error "applyAt: Empty list"
事实上,这与replaceCharInStr
的形状完全相同,因此如果您实现了这一形状,那么您应该能够按照applyAt
实现replaceCharInStr
replaceCharInStr n c xs = applyAt n (\x -> c) xs
-- Or = applyAt n (const c) xs
然后您的replaceChar
函数可以实现为
replaceChar :: Int -> Int -> Char -> [String] -> [String]
replaceChar n m c strings = applyAt n (replaceCharInStr m c) strings
-- Or = applyAt n (applyAt m (const c)) strings
剩下的就是实现
applyAt
首先需要注意:虽然您的签名非常好,但实际上您并没有使用处理字符串的事实,它也可以是任何其他类型的列表。在签名中使用完全通用的类型变量(小写字母)而不是Char
,通常是一个很好的方法:
replaceAtXY :: Int -> Int -> a -> [[a]] -> [[a]]
接下来,请注意,问题基本上可以归结为修改普通(非嵌套)列表的第n个元素。在外部列表中,修改第y个子列表,即在该子列表中修改第x个元素
那么“修改”在Haskell中是什么意思呢?我们不能改变课程2的元素。我们需要一个函数,它接受一个列表并返回另一个列表,并基于一个对列表中的单个元素进行操作的函数来执行此操作
modifyNth :: Int -> (a->a) -> [a]->[a]
注意,这有点类似于标准函数map::(a->b)->[a]->[b]
一旦拥有了该功能,就可以轻松实现
modifyXY :: Int -> Int -> (a->a) -> [[a]]->[[a]]
modifyXY x y f nList = modifyNth y (modifyNth x f) nList
(顺便说一句,nList
参数不需要编写,您可以修改它)
1关于这是一个好主意的原因:显然,它允许您在更一般的设置中使用该功能。但更重要的是,它为类型检查器提供了额外的信息,您不会对包含的元素本身做任何事情。这实际上有助于捕获更复杂应用程序中的许多错误
2实际上,即使语义很好,你也可以在圣单子中使用。首先需要注意的是:虽然你的签名很好,但你实际上没有使用处理字符串的事实,它也可以是任何其他类型的列表。这对我来说通常是个好主意