공백 시퀀스를 단일 문자로 축소하고 문자열 자르기


122

다음 예를 고려하십시오.

"    Hello      this  is a   long       string!   "

나는 그것을 다음과 같이 변환하고 싶다.

"Hello this is a long string!"

답변:


125

OS X 10.7 이상 및 iOS 3.2 이상

hfossli에서 제공 하는 기본 regexp 솔루션을 사용하십시오 .

그렇지 않으면

좋아하는 regexp 라이브러리를 사용하거나 다음 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 2011 년

@lilbyrdie : 이것은 내가 생각하는 문자열, 얼마나 많은 공백이 있는지에 따라 다릅니다. 내 솔루션은 모든 하위 문자열에 대해 새 개체를 만들고 각 하위 문자열에 메서드 호출을 보내기 때문에 매우 느립니다.
Georg Schölly 2011 년

2
좋은 대답, 그렇게 찬성했지만 "쉬움"에 대한 당신의 정의에 도전합니다. 감사합니다, 지금 ;-) ObjC-땅에서 전 파이썬 사람
JK Laiho

2
당신은 '쉬운 해결책이 있으면 복잡한 해결책을 사용하지 말라'고 나를 웃게 만들었습니다. 그래서 가장 쉬운 방법은 [toBeTrimmed stringByReplacingOccurrencesOfString : @ ""withString : @ ""] 아니요? 난 아직 대답을 upvote에 있지만, 확실히 가장 쉬운
마리오 카르발류

2
@ MárioCarvalho 질문은 전체가 아닌 과도한 공백 을 제거 하는 방법을 묻습니다 .
swilliams

52

Regex와 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는 내 책에서 가장 우아한 대답입니다. 또한 .NET에서 정규식을 사용할 수 있다는 것을 방금 배웠습니다 stringByReplacingOccurrencesOfString:. 내가 그것을 몰랐다는 것을 믿을 수 없습니다.
davidf2281

1
대박. 매력처럼 일했다
Kushal Ashok 2015

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 * 백만 라인 엔딩 및 자동 포맷 ... 그것은 "hello______foo"(- 코멘트를 포맷하면 어렵 기 때문에 ""> _ 가정)을 처리하지 않습니다
브라이언 Postow

32
왜 사람들은 질문에 대한 해결책을 제공하지 않는 투표와 답변을합니까? stringByTrimmingCharactersInSet은 문자열의 iside를 분석하지 않고 가장자리 만 분석합니다. Georg Sholly의 답변은 완벽한 것입니다.
Lukasz 2011

3
질문에 대한 답은 아니었지만 확실히 도움이되었습니다. 감사합니다
daveMac 2011

1
동시에 선행 및 후행 공백을 제거하는 탁월한 코드입니다.
user523234 2012

13

정규식을 사용하지만 외부 프레임 워크가 필요하지 않습니다.

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

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

그런 다음 여전히 결과를 다듬어야합니다. 그렇지 않으면 공백이 채워집니다. 이것은 아마도 가장 간단한 대답 일 것입니다.
lilbyrdie 2011-06-23

2
에 대한 문서 NSRegularExpressionSearchrangeOfString:...메서드 에서만 작동한다고 말합니다
user102008

9

한 줄 솔루션 :

NSString *whitespaceString = @" String with whitespaces ";

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

2
나를 도와주었습니다 :). 감사합니다!
thedom 2010

5
이것은 유용하지만 모든 공백을 제거합니다. OP는 기본적으로 공백 압축 (예 : 트림 후 연속 공백을 단일 공백으로 축소)을 원합니다.
lilbyrdie 2011-06-23

또 다른 참고로,이 솔루션은 공백이 아닌 탭이나 줄 바꿈 또는 공백 문자를 처리하지 않습니다.
fwielstra

2
이는 영업 이익은 대답 대신 문자열의 모든 공백을 제거합니다, 당신이 끝날 수 있도록 @ "Stringwithwhitespaces"을하지 않습니다
찰스

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
पवन

4

regex에 대한 또 다른 옵션은 RegexKitLite 이며 iPhone 프로젝트에 포함하기가 매우 쉽습니다.

[theString stringByReplacingOccurencesOfRegex:@" +" withString:@" "];

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 정규 표현식 라이브러리) 사본을 얻으십시오.

전체 기능은 다음과 같습니다.

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 엔진인지 여부는 확실하지 않음)
Kendall Helmstetter Gelner

둘 다 작동 할 것이라고 확신합니다. 나는 regexkit을 사용하지 않았지만 좋은 제안입니다. 사람들은 기본 라이브러리를 기반으로 선택해야합니다 : PERL 호환 pcre (RegExKitLite) 및 Ruby 호환 Oniguruma (OgreKit).
Matt Gallagher

-1

@Mathieu Godart에 따르면 최선의 답변이지만 일부 줄이 누락되어 모든 답변은 단어 사이의 공백을 줄입니다. 그러나 탭이 있거나 탭이있는 경우 다음과 같이 표시됩니다. "이것은 텍스트 \ t이고 \ tTab 사이에, 그래서 "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"

탭을 교체하지 않으면 결과는 다음과 같습니다.

"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

다음 두 가지 정규식은 요구 사항에 따라 작동합니다.

  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

@hfossli 선행 / 후행 공백은 새 / 흰색 라인 문자 세트로 NSString의 stringByTrimmingCharactersInSet : 메소드를 직접 호출하여 제거 할 수 있습니다. 위의 해결책은 위치에 관계없이 중복 공간을 제거하는 것입니다.
apalvai
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.