空白のシーケンスを単一の文字に折りたたみ、文字列をトリムする


122

次の例を検討してください。

"    Hello      this  is a   long       string!   "

それを次のように変換したい:

"Hello this is a long string!"

回答:


125

OS X 10.7以降およびiOS 3.2以降

hfossliが提供するネイティブの正規表現ソリューションを使用します。

さもないと

お気に入りの正規表現ライブラリを使用するか、次のCocoaネイティブソリューションを使用します。

NSString *theString = @"    Hello      this  is a   long       string!   ";

NSCharacterSet *whitespaces = [NSCharacterSet whitespaceCharacterSet];
NSPredicate *noEmptyStrings = [NSPredicate predicateWithFormat:@"SELF != ''"];

NSArray *parts = [theString componentsSeparatedByCharactersInSet:whitespaces];
NSArray *filteredArray = [parts filteredArrayUsingPredicate:noEmptyStrings];
theString = [filteredArray componentsJoinedByString:@" "];

4
これと、両端を削除するためのトリム付きの正規表現の置き換えとのパフォーマンスの比較に興味があります。一方で、対処する正規表現があります。一方、述語があります。どちらも、それぞれの式の内部処理が必要です。
lilbyrdie

@lilbyrdie:これは私が考える文字列、空白の数に依存します。私の解決策は、すべての部分文字列に対して新しいオブジェクトを作成し、それぞれにメソッド呼び出しを送信するため、非常に低速です。
GeorgSchölly11年

2
そのように支持された良い答えですが、私はあなたの「簡単」の定義に挑戦します。よろしくお願いします。元Pythonの人は現在ObjCランドにいます;-)
JK Laiho

2
あなたは私に「簡単な解決策があるなら複雑な解決策を使わないでください」と笑わせました。最も簡単なのは、[toBeTrimmed stringByReplacingOccurrencesOfString:@ "" withString:@ ""]です。私はまだあなたの回答に賛成票を投じていますが、それが間違いなく最も簡単です
マリオカルバーリョ

2
@MárioCarvalho質問では、すべてではなく、余分な空白を削除する方法を尋ねます。
スウィリアムズ2013

52

正規表現とNSCharacterSetはあなたを助けるためにここにあります。このソリューションは、先頭と末尾の空白、および複数の空白を削除します。

NSString *original = @"    Hello      this  is a   long       string!   ";

NSString *squashed = [original stringByReplacingOccurrencesOfString:@"[ ]+"
                                                         withString:@" "
                                                            options:NSRegularExpressionSearch
                                                              range:NSMakeRange(0, original.length)];

NSString *final = [squashed stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

ロギングfinalにより

"Hello this is a long string!"

可能な代替正規表現パターン:

  • スペースのみを置き換える: [ ]+
  • スペースとタブを置き換える: [ \\t]+
  • スペース、タブ、改行を置き換える: \\s+

パフォーマンスランダウン

拡張の容易さ、パフォーマンス、コードの行数、作成されるオブジェクトの数により、このソリューションは適切です。


3
hfossliは私の本の中で最もエレガントな答えです。さらに、で正規表現を使用できることを学びましたstringByReplacingOccurrencesOfString:。知らなかったなんて信じられない。
davidf2281 2013

1
驚くばかり。チャームのように働きました
Kushal Ashok

41

実際には、非常に簡単な解決策があります。

NSString *string = @" spaces in front and at the end ";
NSString *trimmedString = [string stringByTrimmingCharactersInSet:
                                  [NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(@"%@", trimmedString)

出典


29
これにより、先頭と末尾のスペースのみが削除され、それらすべてが削除されると思います。「hello foo」を処理しない
Brian Postow

2
d * mn行末と自動フォーマット...「hello______foo」を処理しません(コメントのフォーマットが難しいため、_-> ""と想定)
Brian Postow

32
なぜあなたは人々が投票し、質問に対する解決策を提供しない回答をするのですか?stringByTrimmingCharactersInSetは文字列のisideを分析せず、エッジのみを分析します。Georg Shollyの回答が最適です。
Lukasz

3
質問に対する正確な回答ではありませんでしたが、それは確かに私を助けました。ありがとう
daveMac

1
先頭と末尾のスペースを同時に削除するための優れたコード。
user523234

13

正規表現を使用しますが、外部フレームワークは必要ありません。

NSString *theString = @"    Hello      this  is a   long       string!   ";

theString = [theString stringByReplacingOccurrencesOfString:@" +" withString:@" "
                       options:NSRegularExpressionSearch
                       range:NSMakeRange(0, theString.length)];

また、結果をトリミングする必要があります。そうしないと、空白が埋め込まれます。しかし、これはおそらく最も簡単な答えです。
lilbyrdie

2
のドキュメントにNSRegularExpressionSearchは、rangeOfString:...メソッドでのみ機能することが記載されています
user102008

9

1行のソリューション:

NSString *whitespaceString = @" String with whitespaces ";

NSString *trimmedString = [whitespaceString
        stringByReplacingOccurrencesOfString:@" " withString:@""];

2
助けてくれました:)。それをありがとう!
thedom 2010

5
これは便利ですが、すべての空白を削除します。OPは基本的に空白の圧縮を必要とします。たとえば、トリムの後に連続する空白を単一の空白に削減します。
lilbyrdie

もう1つの注意点として、このソリューションでは、タブ、改行、スペース以外の空白文字は扱いません。
fwielstra

2
これはOPに応答しませんが、代わりに文字列内のすべてのスペースを削除するため、@ "Stringwithwhitespaces"
charles

6

これでうまくいくはずです...

NSString *s = @"this is    a  string    with lots  of     white space";
NSArray *comps = [s componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

NSMutableArray *words = [NSMutableArray array];
for(NSString *comp in comps) {
  if([comp length] > 1)) {
    [words addObject:comp];
  }
}

NSString *result = [words componentsJoinedByString:@" "];

1
これは実際には文字列「a」で機能しますか?それは、私の知る限り、長さ1のですが、このソリューションは、サイズ0と1で、すべてのスプリットワードを除外します
fwielstra

はいそれは私が期待していた答えです。おかげで1
पवन


3

これを試して

NSString *theString = @"    Hello      this  is a   long       string!   ";

while ([theString rangeOfString:@"  "].location != NSNotFound) {
    theString = [theString stringByReplacingOccurrencesOfString:@"  " withString:@" "];
}

3

以下はNSString拡張機能からのスニペットです。"self"NSStringインスタンスです。渡すことによって、単一の空間に連続した空白を収納するために使用される[NSCharacterSet whitespaceAndNewlineCharacterSet]と、' '二つの引数に。

- (NSString *) stringCollapsingCharacterSet: (NSCharacterSet *) characterSet toCharacter: (unichar) ch {
int fullLength = [self length];
int length = 0;
unichar *newString = malloc(sizeof(unichar) * (fullLength + 1));

BOOL isInCharset = NO;
for (int i = 0; i < fullLength; i++) {
    unichar thisChar = [self characterAtIndex: i];

    if ([characterSet characterIsMember: thisChar]) {
        isInCharset = YES;
    }
    else {
        if (isInCharset) {
            newString[length++] = ch;
        }

        newString[length++] = thisChar;
        isInCharset = NO;
    }
}

newString[length] = '\0';

NSString *result = [NSString stringWithCharacters: newString length: length];

free(newString);

return result;
}

-1

代替ソリューション:OgreKit(Cocoa正規表現ライブラリ)のコピーを自分で入手します。

  • OgreKit(日本語のWebページ-コードは英語)
  • OgreKit(Google自動翻訳):

関数全体は次のようになります。

NSString *theStringTrimmed =
   [theString stringByTrimmingCharactersInSet:
        [NSCharacterSet whitespaceAndNewlineCharacterSet]];
OGRegularExpression  *regex =
    [OGRegularExpression regularExpressionWithString:@"\s+"];
return [regex replaceAllMatchesInString:theStringTrimmed withString:@" "]);

短くて甘い。

最速のソリューションNSScannerが必要な場合は、慎重に作成された一連の命令を使用するのがおそらく最も効果的ですが、これは、巨大な(数メガバイトの)テキストブロックを処理する場合にのみ必要です。


RegExKitLiteの代わりにOgreKitを使用する理由はありますか? regexkit.sourceforge.net 非常によく似たreplaceOccurrencesOfRegex呼び出しがあり、既存のRegEXライブラリの上で動作します(OgreがRegEXエンジン全体であるか
どうか不明

どちらもうまくいくと思います。私は正規表現キットを使用していませんが、良い提案です。PERL互換のpcre(RegExKitLite)とRuby互換のOniguruma(OgreKit)に基づいて選択する必要があります。
マットギャラガー

-1

@Mathieu Godartによると最良の回答ですが、一部の行が欠落しています。すべての回答は単語間のスペースを減らします。のように "3行のコードで私たちはします:私たちが望む文字列は空白を減らします

NSString * str_aLine = @"    this is text \t , and\tTab between      , so on    ";
// replace tabs to space
str_aLine = [str_aLine stringByReplacingOccurrencesOfString:@"\t" withString:@" "];
// reduce spaces to one space
str_aLine = [str_aLine stringByReplacingOccurrencesOfString:@" +" withString:@" "
                                                    options:NSRegularExpressionSearch
                                                      range:NSMakeRange(0, str_aLine.length)];
// trim begin and end from white spaces
str_aLine = [str_aLine stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

結果は

"this is text , and Tab between , so on"

タブを置き換えなければ、resulは次のようになります。

"this is text    , and  Tab between , so on"

-1

単純なwhile引数を使用することもできます。そこにはRegExマジックはないので、将来的には理解して変更する方が簡単かもしれません。

while([yourNSStringObject replaceOccurrencesOfString:@"  "
                         withString:@" "
                         options:0
                         range:NSMakeRange(0, [yourNSStringObject length])] > 0);

1
質問には答えません:)先頭と末尾の空白を削除しません。
hfossli 2014年

-1

次の2つの正規表現は要件に応じて機能します

  1. 空白とタブを一致させるための@ "+"
  2. @ "\\ s {2、}"は、一致する空白、タブ、改行

次に、nsstringのインスタンスメソッドを適用します。 stringByReplacingOccurrencesOfString:withString:options:range:をして、それらを単一の空白で置き換えます。

例えば

[string stringByReplacingOccurrencesOfString:regex withString:@" " options:NSRegularExpressionSearch range:NSMakeRange(0, [string length])];

注:iOS 5.x以降では、上記の機能に「RegexKitLite」ライブラリを使用しませんでした。


このソリューションは、OPが要求するように、先頭と末尾の空白を削除しません。
hfossli 14

@hfossliの先頭/末尾のスペースは、NSStringのstringByTrimmingCharactersInSet:メソッドを直接呼び出して、新しい/白い線の文字セットで削除できます。上記の解決策は、場所に関係なく冗長なスペースを削除することでした。
apalvai 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.