文字列から特定の重複を削除する方法を知りたいです。例は次のとおりです。
"|Hello|| My|| Name|| Is|| XYZ|"
次のようになる必要があります。
"|Hello| My| Name| Is| XYZ|"
ありがとう
文字列から特定の重複を削除する方法を知りたいです。例は次のとおりです。
"|Hello|| My|| Name|| Is|| XYZ|"
次のようになる必要があります。
"|Hello| My| Name| Is| XYZ|"
ありがとう
自分で許可する場合Data.List.Split(そうするべきです!)、文字列を次のように単語に分割できます
splitOn "|" "|Hello|| My|| Name|| Is|| XYZ|"
利回り
["","Hello",""," My",""," Name",""," Is",""," XYZ",""]
""出現するすべての単語をwithに置き換えてから"|"、単語を結合します。これは単に次のように を呼び出すだけですconcatMap:
concatMap (\s -> if s == "" then "|" else s) $
splitOn "|" "|Hello|| My|| Name|| Is|| XYZ|"
利回り
"|Hello| My| Name| Is| XYZ|"
別の方法として"||"、部品を分割して結合し、その間に挿入することもでき"|"ます。これだけ
intercalate "|" $ splitOn "||" "|Hello|| My|| Name|| Is|| XYZ|"
さらに別の代替手段であり、奇妙なエッジケースで失敗した場合に修正するのがおそらく最も簡単なのは、正規表現を使用することです。次のようになります。
subRegex (mkRegex "\\|\\|") "|Hello|| My|| Name|| Is|| XYZ|" "|"
|簡単に修正できるという意味を示すために、任意の数のs を 1 つの s だけに減らしたいと想像してください|。正規表現ソリューションでは、正規表現を次のように変更するだけです。
> subRegex (mkRegex "\\|+") "|||Hello||||||| My|| Name|||| Is|| XYZ|||||" "|"
"|Hello| My| Name| Is| XYZ|"
非常にシンプルで明白な解決策は、ダブル ヘッドでパターン マッチを行うことです。
foo :: Char -> String -> String
foo elem (xa:xb:xs) = ...
次に、xaが と等しいかどうかを確認xbし、残りの部分と一緒に両方を返すか、重複している場合は 1 つだけを返し、1 文字前に移動します。
ここでの重要な問題は、2 つ以上続けて何をするかです|。ここで提供されるソリューションは、この特定の側面で大きく異なります。
の重複排除を||||「別の | の前に | を削除する」と|解釈"Hello ||||"し"Hello |||"ますか?
の重複排除を||||「|| のすべてのペアを 1 つの | に減らす」と解釈"Hello ||||"し"Hello ||"ますか?
の重複排除を||||「特異点のみが発生するまで文字列を減らす」と解釈"Hello ||||"し"Hello |"ますか?
したがって、(1) の解決策が提案されました。(2) と (3) のソリューションは、互いに同様の方法で構築できます。
(2) の解決策:
dedup c (x:y:xs) | x == c && x == y = x: dedup c xs
dedup c (x:xs) = x: dedup c xs
dedup c _ = []
(3) の解決策:
dedup c (x:y:xs) | x == c && x == y = dedup c (y:xs)
dedup c (x:xs) = x: dedup c xs
dedup c _ = []
ペアが見つかったときに追加するタイミングを微調整するだけで|、動作に大きな違いが生じます。
import Data.List.Split(splitOn)
removeDup d = concat . map rep . splitOn d
where
rep s = if null s then d else s
> removeDup "|" "|Hello|| My|| Name|| Is|| XYZ|"
"|Hello| My| Name| Is| XYZ|"
ghci> :m Data.List
ghci> let myGroupFunc = groupBy (\a b -> a == '|' && b == '|')
ghci> map head $ myGroupFunc "|Hello|| My|| Name|| Is|| XYZ|"
"|Hello| My| Name| Is| XYZ|"
ghci>
groupByタイプ(a -> a -> Bool) -> [a] -> [[a]]です。関数とリストを受け取り、リストのリストを返します。groupBytype の関数(a -> a -> Bool)(これを と呼びますf) を取り、リストをトラバースして、時間の 2 つの要素を渡します。fが返される場合True、2 つの要素が同じサブリストにまとめられます。一方、fが返される場合False、新しいサブリストが作成されます。
実験する 1 つの方法groupByは、次のように設定fすること(==)です。
ghci> groupBy (==) "aaabbbcccdeffg"
["aaa","bbb","ccc","d","e","ff","g"]
これにより、要素が等しい場合またはreturn の場合に要素がグループ化されるため、同じ文字がグループ化されます(==)。True
(余談ですが、Haskell では、 aStringは実際には a[Char]であるため、 の同等の表現"aaabbbcccdeffg"は次のようになります。['a','a','a','b','b','b','c','c','c','d','e','f','f',g']
結果の同等の表現は次のとおりです。
[['a','a','a'],['b','b','b'],['c','c','c'],['d'],['e'],['f','f'],['g']].)
groupBy (==)サンプル入力を試してみましょう。
ghci> groupBy (==) "|Hello|| My|| Name|| Is|| XYZ|"
["|","H","e","ll","o","||"," ","M","y","||"," ","N","a","m","e","||"," ","I","s","||"," ","X","Y","Z","|"]
要素のペアが同じになるたびに、要素をグループ化することに注意してください。しかし、それはあなたが望むものではありませ"ll"ん"Hello".
そのため、要素のペアが同じであり、それらが必要な文字である場合groupByにのみ返すように、渡される関数を変更します: :True'|'
ghci> groupBy (\a b -> a == '|' && b == '|') "|Hello|| My|| Name|| Is|| XYZ|"
["|","H","e","l","l","o","||"," ","M","y","||"," ","N","a","m","e","||"," ","I","s","||"," ","X","Y","Z","|"]
まとめたい文字のみをグループ化することに注意してください'|'。ここで、複製された要素の 1 つだけが必要なため、Charそれぞれの最初の要素Stringを取得して結合し、結果を取得できます。
ghci> map head $ groupBy (\a b -> a == '|' && b == '|') "|Hello|| My|| Name|| Is|| XYZ|"
"|Hello| My| Name| Is| XYZ|"
これは、この回答の冒頭からの解決策です。式fを使用せずに直接適用することを受け入れてください。let