Haskellで文字列の最初のスペースを削除するにはどうすればよいですか?
例えば:
removeSpace " hello" = "hello"
removeSpace " hello" = " hello"
removeSpace "hello" = "hello"
Haskellで文字列の最初のスペースを削除するにはどうすればよいですか?
例えば:
removeSpace " hello" = "hello"
removeSpace " hello" = " hello"
removeSpace "hello" = "hello"
いくつかの機能と実行方法を示すために、複数のスペース削除オプションがあります。
複数のスペースを取るには、次のことができます
removeSpaces = dropWhile (==' ')
これは と同じ意味removeSpaces xs = dropWhile (==' ') xs
ですが、部分的な適用を使用します ((==' ')
本質的にはそうです)。
または、より一般的な削除については、
import Data.Char
removeWhitespace = dropWhile isSpace
スペースを 1 つだけ取りたいと本当に確信している場合 (そして、そのように思われる場合) は、パターン マッチングが最も明確です。
removeASpace (' ':xs) = xs -- if it starts with a space, miss that out.
removeASpace xs = xs -- otherwise just leave the string alone
これは haskell で機能するため、 list で始まり、 list で続くリストを意味String = [Char]
します。(x:xs)
x
xs
1 つの空白文字を削除するには、関数ガードを使用できます (まだ使用していない場合は、非常に軽い構文の if ステートメント)。
removeAWhitespace "" = "" -- base case of empty string
removeAWhitespace (x:xs) | isSpace x = xs -- if it's whitespace, omit it
| otherwise = x:xs -- if it's not keep it.
単純にパターン マッチングを使用します。
removeSpace (' ':xs) = xs
removeSpace xs = xs
Haskell では、文字列は単に文字のリストです。つまり、Prelude が定義します。
type String = [Char]
さらに、関数を記述する方法は約 3 つあります。
Haskell と関数型プログラミングに慣れていない場合は、最初の方法を使用してほとんどの関数を作成し、その後、より多くの定義済み関数を使用するように徐々に移行することをお勧めします。
文字列内の最初のスペース文字 ( ) を削除するという問題に対して、' '
パターン マッチングと再帰は実際には非常に理にかなっています。前述のように、文字列は単なる文字のリストであるため、単純なリスト トラバーサルしかできません。
まず、関数の署名を書きましょう。
removeSpace :: [Char] -> [Char]
(ここでリストトラバーサルを実行していることを明示するので[Char]
はなく、書いています。)String
リストに対するパターン マッチングでは、2 つのケースを考慮する必要があります。リストが空の場合 ( []
) と、head 要素の後に末尾が続くリスト ( c : cs
) です。
空のリストの処理は、いつものように単純です。文字が残っていないため、削除するものはもうなく、空のリストを返すだけです。
removeSpace [] = []
次に、先頭要素 (文字) と末尾リストがある状況です。ここでも、先頭文字がスペースの場合とそれ以外の文字の場合の 2 つのケースを区別する必要があります。
先頭文字がスペースの場合、最初に遭遇するスペースになるため、それを削除する必要があります。最初のスペースのみを削除する必要があるため、それ以上処理せずにリストの残り (つまり末尾) を返すことができます。
removeSpace (' ' : cs) = cs
あとは先頭文字がスペースでない場合の対応です。次に、返されたリストにそれを保持する必要があり、さらに、リストの残りの部分で最初のスペースを探し続ける必要があります。つまり、関数を末尾に再帰的に適用する必要があります。
removeSpace (c : cs) = c : removeSpace cs
それだけです。関数の完全な定義は次のようになります
removeSpace :: [Char] -> [Char]
removeSpace [] = []
removeSpace (' ' : cs) = cs
removeSpace (c : cs) = c : removeSpace cs
これは、事前定義された関数を巧みに組み合わせたものと同じくらい明確で簡潔な定義です。
最後に、関数をテストしましょう。
> removeSpace " hello"
"hello"
> removeSpace " hello"
" hello"
> removeSpace "hello"
"hello"
事前定義された関数から関数を本当に構築したい場合removeSpace
は、トリックを実行する別の定義を次に示します。
removeSpace :: [Char] -> [Char]
removeSpace = uncurry (flip (flip (++) . drop 1)) . break (== ' ')
(明示的なパターン マッチングと再帰を使用する方法を好む理由がわかります。;-))
注: 最初のスペースがどこに現れても、文字列の最初のスペースを削除することが目的であると想定しています。あなたが与えた例では、最初のスペースは常に文字列の最初の文字です。常にそうである場合、つまり先頭のスペースを削除しただけの場合は、再帰を省略して単純に次のように書くことができます。
removeSpace :: [Char] -> [Char]
removeSpace [] = []
removeSpace (' ' : cs) = cs
removeSpace (c : cs) = c : cs
または、最初と最後のケースを組み合わせて、
removeSpace :: [Char] -> [Char]
removeSpace (' ' : cs) = cs
removeSpace cs = cs
または、事前定義された関数を使用して、
removeSpace :: [Char] -> [Char]
removeSpace = uncurry ((++) . drop 1) . span (== ' ')
文字列の任意の場所で最初のスペースを削除するには:
removeSpace :: String -> String
removeSpace = (\(xs,ys) -> xs ++ drop 1 ys) . span (/=' ')
スペースspan
が見つかるか、文字列の最後に到達するまで文字を取得します。
次に、結果を分割してタプルに入れ、2番目のリスト(スペース)の最初の文字をスキップして、取得して結合します。さらに、残りは(空のリスト)ではないと主張しnull
ます-もしそうなら、空のリストはテールを持つことができないので、テールを取得することはできませんか?したがって、そうである場合は、空のリストを返すだけです。