问题描述
我正在尝试编写一个Haskell函数,该函数接受一对成对的字母,并将所有成对的字母交换为所有字母的字符串,但是我的想法很尴尬且很单调.
I'm trying to write a Haskell function that takes a string of pairs of letters, and exchanges the letters of the pair in a string of all letters, but what I've come up with feels awkward and unidiomatic.
我有
swap a b = map (\x-> if x == a then b else if x == b then a else x)
sub n = foldr (.) id (zipWith swap (head <$> splitOn "." n) (last <$> splitOn "." n)) ['A'..'Z']
效果很好
> sub "RB.XD.EU.ZM.IJ"
"ARCXUFGHJIKLZNOPQBSTEVWDYM"
和
> sub "YC.LU.EB.TZ.RB.XD.IJ"
"ARYXBFGHJIKUMNOPQESZLVWDCT"
但是我对Haskell还是陌生的,感觉就像是我的方法—特别是我的swap
辅助函数(我只在这里使用)—比需要的要复杂.
but I'm new to Haskell and feel like my approach — especially my swap
helper function (which I only use here) — is more elaborate than it needs to be.
是否有更好,更惯用的方法来解决此问题;尤其是利用我错过的语言功能,内置功能或库功能的功能?
Is there a better, more idiomatic, approach to this problem; especially one that takes advantage of a language feature, builtin, or library function that I've missed?
推荐答案
在替换列表上进行左折会使代码更短:
Doing a left fold over the substitution list makes the code shorter:
import Data.List
import Data.List.Split
sub = foldl' swap ['A'..'Z'] . splitOn "." . reverse
where
swap az [a,b] = map (\x -> if x == a then b else if x == b then a else x) az
如果您不在意先交换EB
还是RB
,则放弃相反的操作.
Drop the reverse if you don't care whether EB
or RB
is swapped first.
如果您要替换而不是交换:
If you'd want to replace instead of a swap:
import Data.List
import Data.List.Split
replace needle replacement haystack =
intercalate replacement (splitOn needle haystack)
rep = foldl' replace' ['A'..'Z'] . splitOn "."
where
replace' az [a,b] = replace [a] [b] az
这篇关于在Haskell字符串中交换多对字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!