2012-11-13 36 views
12

Cho một chuỗi, tôi cần lấy số lượng mỗi từ xuất hiện trong chuỗi đó. Để làm như vậy, tôi trích xuất chuỗi thành một mảng, theo từ, và tìm kiếm theo cách đó, nhưng tôi có cảm giác rằng việc tìm kiếm chuỗi trực tiếp là tối ưu hơn. Dưới đây là mã mà tôi đã viết ban đầu để giải quyết vấn đề. Tôi đang lên cho các đề xuất về các giải pháp tốt hơn mặc dù.iOS - Cách hiệu quả nhất để tìm số lần xuất hiện từ trong một chuỗi

NSMutableDictionary *sets = [[NSMutableDictionary alloc] init]; 

NSString *paragraph = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"text" ofType:@"txt"] encoding:NSUTF8StringEncoding error:NULL]; 

NSMutableArray *words = [[[paragraph lowercaseString] componentsSeparatedByString:@" "] mutableCopy]; 

while (words.count) { 
    NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init]; 
    NSString *search = [words objectAtIndex:0]; 
    for (unsigned i = 0; i < words.count; i++) { 
     if ([[words objectAtIndex:i] isEqualToString:search]) { 
      [indexSet addIndex:i]; 
     } 
    } 
    [sets setObject:[NSNumber numberWithInt:indexSet.count] forKey:search]; 
    [words removeObjectsAtIndexes:indexSet]; 
} 

NSLog(@"%@", sets); 

Ví dụ:

Bắt đầu chuỗi:
". Đây là một thử nghiệm này chỉ là một thử nghiệm"

Kết quả:

  • "Đây" - 2
  • "là" - 2
  • "a" - 2
  • "test" - 2
  • "chỉ" - 1
+0

Phương pháp của bạn có hoạt động không? Bạn không có vấn đề với biểu tượng dấu chấm? Tôi đoán bạn nên có "thử nghiệm". thay vì "thử nghiệm". – Ricardo

Trả lời

23

Đây chính là điều mà NSCountedSet dành cho.

Bạn cần chia chuỗi thành các từ (mà iOS đủ đẹp để cung cấp cho chúng ta chức năng để chúng tôi không phải lo lắng về dấu chấm câu) và chỉ thêm từng chuỗi vào bộ đếm theo dõi số lần mỗi đối tượng xuất hiện trong tập hợp:

NSString  *string  = @"This is a test. This is only a test."; 
NSCountedSet *countedSet = [NSCountedSet new]; 

[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) 
          options:NSStringEnumerationByWords | NSStringEnumerationLocalized 
         usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){ 

          // This block is called once for each word in the string. 
          [countedSet addObject:substring]; 

          // If you want to ignore case, so that "this" and "This" 
          // are counted the same, use this line instead to convert 
          // each word to lowercase first: 
          // [countedSet addObject:[substring lowercaseString]]; 
         }]; 

NSLog(@"%@", countedSet); 

// Results: 2012-11-13 14:01:10.567 Testing App[35767:fb03] 
// <NSCountedSet: 0x885df70> (a [2], only [1], test [2], This [2], is [2]) 
+0

OMG!Điều đó thậm chí còn dễ hơn tôi tưởng tượng! Cảm ơn bạn! – RyJ

+0

Bạn được chào đón! – lnafziger

+0

@Inafzinger Nhưng có vấn đề nhỏ trong này, khi tôi muốn đếm số lượng từ trong NSString có chứa một số thẻ html, bỏ qua chúng. Nhưng tôi cũng muốn đếm chúng. Bất kỳ ý tưởng cho việc này. –

2

Nếu tôi phải đoán, tôi sẽ nói NSRegularExpression cho điều đó. Như thế này:

NSUInteger numberOfMatches = [regex numberOfMatchesInString:string 
                options:0 
                 range:NSMakeRange(0, [string length])]; 

Đoạn mã đó được lấy từ here.


Sửa 1.0:

Dựa trên những gì Sir Till cho biết:

NSString *string = @"This is a test, so it is a test"; 

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 
NSArray *arrayOfWords = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 
for (NSString *word in arrayOfWords) 
{ 
    if ([dictionary objectForKey:word]) 
    { 
     NSNumber *numberOfOccurences = [dictionary objectForKey:word]; 
     NSNumber *increment = [NSNumber numberWithInt:(1 + [numberOfOccurences intValue])]; 
     [dictionary setValue:increment forKey:word]; 
    } 
    else 
    { 
     [dictionary setValue:[NSNumber numberWithInt:1] forKey:word]; 
    } 
} 

Bạn nên cẩn thận với:

  • dấu hiệu Punctuation. (nói cách khác)
  • từ UpperCase so với từCase thấp hơn.
+0

Tôi cần đếm mỗi từ. Vì vậy, trong chuỗi, "Đây là một thử nghiệm. Đây chỉ là một thử nghiệm." "kiểm tra" sẽ có tổng số là 2 "," số này sẽ có tổng là 2, "chỉ" sẽ có tổng số là 1, v.v. – RyJ

+0

Kiểm tra chỉnh sửa của tôi .. – Peres

1

Tôi nghĩ rằng đó thực sự là ý tưởng tồi khi bạn cố gắng tìm kiếm một từ trong đoạn dài bằng một vòng lặp. Bạn nên sử dụng một biểu thức chính quy để làm điều đó! Tôi biết nó không phải là dễ dàng ở lần đầu tiên để tìm hiểu nó, nhưng nó thực sự đáng để biết điều đó! Hãy nhìn vào trường hợp này Use regular expression to find/replace substring in NSString

Các vấn đề liên quan