Thu gọn chuỗi khoảng trắng thành một ký tự và cắt chuỗi


122

Hãy xem xét ví dụ sau:

"    Hello      this  is a   long       string!   "

Tôi muốn chuyển đổi nó thành:

"Hello this is a long string!"

Câu trả lời:


125

OS X 10.7+ và iOS 3.2+

Sử dụng giải pháp regexp gốc do hfossli cung cấp.

Nếu không thì

Sử dụng thư viện regexp yêu thích của bạn hoặc sử dụng giải pháp gốc Cacao sau:

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
Tôi rất tò mò về một so sánh hiệu suất của điều này với một thay thế regex với một phần cắt để loại bỏ các đầu. Một mặt, bạn có một regex để đối phó. Mặt khác, bạn có một vị ngữ. Yêu cầu xử lý nội bộ của các biểu thức tương ứng.
lilbyrdie

@lilbyrdie: Điều này phụ thuộc vào chuỗi mà tôi nghĩ, có bao nhiêu khoảng trắng. Giải pháp của tôi khá chậm, vì nó tạo một đối tượng mới cho mọi chuỗi con và gửi các cuộc gọi phương thức đến từng chuỗi đó.
Georg Schölly

2
Câu trả lời tốt, được tán thành như vậy, nhưng tôi thách thức định nghĩa của bạn về "dễ dàng". Trân trọng, cựu anh chàng Python hiện đang ở ObjC-land ;-)
JK Laiho,

2
Bạn đã khiến tôi bật cười với câu nói "đừng sử dụng các giải pháp phức tạp nếu có một giải pháp dễ dàng". Vì vậy, cách dễ nhất là [toBeTrimmed stringByReplacingOccurrencesOfString: @ "" withString: @ ""] không? Tôi vẫn upvote câu trả lời của bạn, nhưng nó chắc chắn là dễ nhất
Mário Carvalho

2
@ MárioCarvalho Câu hỏi đặt ra là làm thế nào để loại bỏ khoảng trắng dư thừa , không phải tất cả.
swilliams

52

Regex và NSCharacterSet sẵn sàng trợ giúp bạn. Giải pháp này cắt bỏ khoảng trắng đầu và cuối cũng như nhiều khoảng trắng.

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]];

Ghi nhật ký finalmang lại

"Hello this is a long string!"

Các mẫu regex thay thế có thể có:

  • Chỉ thay thế khoảng trắng: [ ]+
  • Thay thế khoảng trắng và các tab: [ \\t]+
  • Thay thế khoảng trắng, tab và dòng mới: \\s+

Tóm tắt hiệu suất

Tính dễ mở rộng, hiệu suất, số dòng mã và số lượng đối tượng được tạo làm cho giải pháp này trở nên phù hợp.


3
hfossli's là câu trả lời thanh lịch nhất, trong cuốn sách của tôi. Thêm vào đó, tôi vừa biết bạn có thể sử dụng biểu thức chính quy trong stringByReplacingOccurrencesOfString:. Không thể tin rằng tôi đã không biết điều đó.
davidf2281

1
Tuyệt vời. Làm việc như một sự quyến rũ
Kushal Ashok

41

Trên thực tế, có một giải pháp rất đơn giản cho điều đó:

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

( Nguồn )


29
Tôi nghĩ rằng điều này sẽ chỉ loại bỏ các khoảng trống ở đầu và cuối, và loại bỏ tất cả chúng. nó sẽ không đối phó với "hello foo"
Brian Postow 15/09/09

2
d * kết thúc dòng mn và tự động định dạng ... nó không đối phó với "hello______foo" (giả _ -> "" vì định dạng comments là cứng)
Brian Postow

32
Tại sao mọi người bỏ phiếu cho bạn và câu trả lời không cung cấp giải pháp cho câu hỏi? stringByTrimmingCharactersInSet cũng không phân tích mặt bên của chuỗi mà chỉ phân tích các cạnh. Câu trả lời của Georg Sholly là câu trả lời hoàn hảo.
Lukasz

3
Không phải là một câu trả lời chính xác cho câu hỏi, nhưng nó chắc chắn đã giúp tôi. Cảm ơn
daveMac

1
Mã tuyệt vời để loại bỏ khoảng trắng đầu và cuối cùng một lúc.
user523234

13

Với regex, nhưng không cần bất kỳ khung bên ngoài nào:

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

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

Sau đó, bạn vẫn cần phải cắt bớt kết quả, nếu không bạn sẽ bị chèn khoảng trắng. Tuy nhiên, đây có lẽ là câu trả lời đơn giản nhất.
lilbyrdie

2
tài liệu cho NSRegularExpressionSearchbiết rằng nó chỉ làm việc với các rangeOfString:...phương pháp
user102008

9

Một giải pháp một dòng:

NSString *whitespaceString = @" String with whitespaces ";

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

2
Đã giúp tôi ra ngoài :). Cảm ơn vì điều đó!
thedom

5
Mặc dù điều này hữu ích nhưng nó sẽ loại bỏ tất cả khoảng trắng. OP về cơ bản muốn nén khoảng trắng, ví dụ như cắt bớt các khoảng trắng liên tiếp thành một khoảng trắng duy nhất.
lilbyrdie

Một lưu ý khác, giải pháp này không xử lý các tab hoặc dòng mới hoặc các ký tự khoảng trắng ngoài dấu cách.
fwielstra

2
Này không trả lời OP, nhưng thay vì loại bỏ tất cả các khoảng trống trong chuỗi, do đó bạn kết thúc với @ "Stringwithwhitespaces"
charles

6

Điều này nên làm điều đó ...

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
Điều này có thực sự hoạt động với chuỗi 'a' không? Đó là chiều dài 1, như xa như tôi có thể thấy, giải pháp này sẽ lọc ra tất cả các từ chia tay với kích thước 0 và 1.
fwielstra

Vâng, đó là câu trả lời tôi đã mong đợi. Cảm ơn +1
पवन

4

Một tùy chọn khác cho regex là RegexKitLite , rất dễ nhúng vào dự án iPhone:

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

3

Thử cái này

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

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

3

Dưới đây là một đoạn trích từ một NSStringphần mở rộng, nơi "self"NSStringví dụ. Nó có thể được sử dụng để thu gọn khoảng trắng liền kề thành một khoảng trắng duy nhất bằng cách chuyển vào [NSCharacterSet whitespaceAndNewlineCharacterSet]' 'chuyển đến hai đối số.

- (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

Giải pháp thay thế: kiếm cho mình một bản sao của OgreKit (thư viện biểu thức chính quy Cocoa).

  • OgreKit (trang web tiếng Nhật - mã bằng tiếng Anh)
  • OgreKit (dịch tự động của Google):

Toàn bộ chức năng sau đó là:

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

Ngắn và ngọt.

Nếu bạn đang theo đuổi giải pháp nhanh nhất, một loạt hướng dẫn được xây dựng cẩn thận NSScannercó thể sẽ hoạt động tốt nhất nhưng điều đó chỉ cần thiết nếu bạn định xử lý khối văn bản khổng lồ (nhiều megabyte).


Có lý do gì để sử dụng OgreKit thay vì RegExKitLite? regexkit.sourceforge.net Nó có một cuộc gọi replaceOccurrencesOfRegex rất giống nhau, và các công trình trên đầu trang của các thư viện regex hiện có (không chắc chắn nếu Ogre là một công cụ toàn regex hoặc những gì)
Kendall Helmstetter Gelner

Tôi chắc chắn rằng cả hai sẽ hoạt động. Tôi chưa sử dụng regexkit nhưng đó là một gợi ý tốt để thực hiện. Mọi người nên chọn dựa trên các thư viện cơ bản: pcre tương thích với PERL (RegExKitLite) và Oniguruma tương thích với Ruby (OgreKit).
Matt Gallagher

-1

theo @Mathieu Godart là câu trả lời hay nhất, nhưng thiếu một số dòng, tất cả các câu trả lời chỉ làm giảm khoảng cách giữa các từ, nhưng khi có tab hoặc có tab ở vị trí, như thế này: "đây là văn bản \ t và \ tTab ở giữa, vân vân "trong mã ba dòng, chúng ta sẽ: chuỗi chúng ta muốn giảm khoảng trắng

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]];

kết quả là

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

mà không cần thay thế tab, resul sẽ là:

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

-1

Bạn cũng có thể sử dụng một đối số while đơn giản. Không có phép thuật RegEx nào ở đó, vì vậy có thể dễ hiểu hơn và thay đổi trong tương lai:

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

1
Không trả lời câu hỏi :) Nó không loại bỏ khoảng trắng đầu và cuối.
hfossli

-1

Hai biểu thức chính quy sau sẽ hoạt động tùy thuộc vào yêu cầu

  1. @ "+" để khớp các khoảng trắng và tab
  2. @ "\\ s {2,}" để khớp với khoảng trắng, tab và ngắt dòng

Sau đó, áp dụng phương thức thể hiện của nsstring stringByReplacingOccurrencesOfString:withString:options:range:để thay thế chúng bằng một khoảng trắng duy nhất.

ví dụ

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

Lưu ý: Tôi đã không sử dụng thư viện 'RegexKitLite' cho chức năng trên cho iOS 5.x trở lên.


Giải pháp này không loại bỏ khoảng trắng đầu và cuối như OP yêu cầu.
hfossli

@hfossli các khoảng trống ở đầu / cuối có thể được loại bỏ bằng cách gọi trực tiếp phương thức stringByTrimmingCharactersInSet: của NSString với bộ ký tự dòng trắng / mới. Giải pháp trên là loại bỏ các không gian thừa độc lập với vị trí của chúng.
apalvai
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.