0

文字列から特定の重複を削除する方法を知りたいです。例は次のとおりです。

"|Hello|| My|| Name|| Is|| XYZ|"

次のようになる必要があります。

"|Hello| My| Name| Is| XYZ|"

ありがとう

4

5 に答える 5

4

自分で許可する場合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|"
于 2013-09-18T12:00:52.787 に答える
2

非常にシンプルで明白な解決策は、ダブル ヘッドでパターン マッチを行うことです。

foo :: Char -> String -> String
foo elem (xa:xb:xs) = ...

次に、xaが と等しいかどうかを確認xbし、残りの部分と一緒に両方を返すか、重複している場合は 1 つだけを返し、1 文字前に移動します。

于 2013-09-18T11:14:55.980 に答える
1

ここでの重要な問題は、2 つ以上続けて何をするかです|。ここで提供されるソリューションは、この特定の側面で大きく異なります。

  1. の重複排除を||||「別の | の前に | を削除する」と|解釈"Hello ||||""Hello |||"ますか?

  2. の重複排除を||||「|| のすべてのペアを 1 つの | に減らす」と解釈"Hello ||||""Hello ||"ますか?

  3. の重複排除を||||「特異点のみが発生するまで文字列を減らす」と解釈"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 _ = []

ペアが見つかったときに追加するタイミングを微調整するだけで|、動作に大きな違いが生じます。

于 2013-09-18T13:27:31.263 に答える
-2
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|"
于 2013-09-18T11:42:58.987 に答える
-2
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

于 2013-09-18T11:19:32.663 に答える