Mam NSString
lub NSMutableString
i chciałbym uzyskać liczbę wystąpień określonego znaku.Liczba wystąpień znaku w NSString
Muszę to zrobić dla kilku znaków - w tym przypadku wielkich angielskich znaków - więc byłoby miło, gdyby było szybkie.
Mam NSString
lub NSMutableString
i chciałbym uzyskać liczbę wystąpień określonego znaku.Liczba wystąpień znaku w NSString
Muszę to zrobić dla kilku znaków - w tym przypadku wielkich angielskich znaków - więc byłoby miło, gdyby było szybkie.
replaceOccurrencesOfString:withString:options:range:
spowoduje zwrócenie liczby znaków zastąpionych w NSMutableString
.
[string replaceOccurrencesOfString:@"A"
withString:@"B"
options:NSLiteralSearch
range:NSMakeRange(0, [receiver length])];
I prawdopodobnie używać
NSString rangeOfCharacterFromSet:
lub
rangeOfCharacterFromSet:options:range::
gdzie zbiór jest zbiorem znaków szukasz. Zwraca z lokalizacją pierwszego znaku pasującego do zestawu. Zachowaj tablicę lub słownik i zwiększ liczbę znaków, a następnie powtórz.
Gdy szukasz rzeczy w NSString
, spróbuj użyć NSScanner
pierwszy.
NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *scanner = [NSScanner scannerWithString:yourString];
NSCharacterSet *charactersToCount = @"C" // For example
NSString *charactersFromString;
if (!([scanner scanCharactersFromSet:charactersToCount
intoString:&charactersFromString])) {
// No characters found
NSLog(@"No characters found");
}
// should return 2 for this
NSInteger characterCount = [charactersFromString length];
Nie byłem w stanie w ogóle uruchomić tego. Próbuję policzyć liczbę spacji. – lawrence
@lawrence Domyślnie spacje i białe spacje są ignorowane przez NSScanner. – borrrden
Możesz wywołać 'setCharactersToBeSkipped: (NSCharacterSet *) skipSet' z' nil' jako 'skipSet' - a' NSScanner' nie pominie żadnych znaków. –
Przykład ze skanerem ulegał awarii na iPhonie. Znalazłem to rozwiązanie:
NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *mainScanner = [NSScanner scannerWithString:yourString];
NSString *temp;
NSInteger numberOfChar=0;
while(![mainScanner isAtEnd])
{
[mainScanner scanUpToString:@"C" intoString:&temp];
numberOfChar++;
[mainScanner scanString:@"C" intoString:nil];
}
Udało mi się to bez awarii. Mam nadzieję, że to pomoże!
Twoje rozwiązanie nie działa dla mnie, dodałem warunek w pętli, aby zwiększyć numberOfChar tylko jeśli mainScanner osiągnie koniec łańcucha:
NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *mainScanner = [NSScanner scannerWithString:yourString];
NSString *temp;
NSInteger numberOfChar=0;
while(![mainScanner isAtEnd])
{
[mainScanner scanUpToString:@"C" intoString:&temp];
if(![mainScanner isAtEnd]) {
numberOfChar++;
[mainScanner scanString:@"C" intoString:nil];
}
}
pamiętać, że jest szybkie ustalenie, I don nie ma czasu na zrobienie eleganckiego rozwiązania ...
Możesz to zrobić w jednym wierszu. Na przykład ten zlicza ilość miejsc:
NSUInteger numberOfOccurrences = [[yourString componentsSeparatedByString:@" "] count] - 1;
Tworzy tymczasową tablicę. Aby uzyskać szybkość, należy preferować [odpowiedź Jacque'a] (http://stackoverflow.com/a/15947190/482601). – fabian789
Czy to policzy spację na początku i końcu 'yourString'? –
Różnica prędkości będzie miała znaczenie tylko wtedy, gdy robisz to tysiące razy. –
Spróbuj kategorię na NSString:
@implementation NSString (OccurrenceCount)
- (NSUInteger)occurrenceCountOfCharacter:(UniChar)character
{
CFStringRef selfAsCFStr = (__bridge CFStringRef)self;
CFStringInlineBuffer inlineBuffer;
CFIndex length = CFStringGetLength(selfAsCFStr);
CFStringInitInlineBuffer(selfAsCFStr, &inlineBuffer, CFRangeMake(0, length));
NSUInteger counter = 0;
for (CFIndex i = 0; i < length; i++) {
UniChar c = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, i);
if (c == character) counter += 1;
}
return counter;
}
@end
ten jest około 5 razy szybciej niż podejście componentsSeparatedByString:
.
Ta kategoria działa dobrze, ale mam pytanie: czy możesz używać zarówno UniChar (z CFString.h), jak i unichar (z NSString) jako takich samych? – Bjinse
Obecnie pierwszą rzeczą, która przyjdzie mi do głowy coś takiego: NSCountedSet
NSString *string [email protected]"AAATTC";
NSMutableArray *array = [@[] mutableCopy];
[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[array addObject:substring];
}] ;
NSCountedSet * set = [[NSCountedSet alloc] initWithArray:array];
for (NSString *nucleobase in @[@"C", @"G", @"A", @"T"]){
NSUInteger count = [set countForObject:nucleobase];
NSLog(@"%@: %lu", nucleobase, (unsigned long)count);
}
kłody:
C: 1
G: 0
A: 3
T: 2
Oto Swift 3 wersja działa na NSRange, zakres, String i NSString! Ciesz się :)
/// All ranges using NSString and NSRange
/// Is usually used together with NSAttributedString
extension NSString {
public func ranges(of searchString: String, options: CompareOptions = .literal, searchRange: NSRange? = nil) -> [NSRange] {
let searchRange = searchRange ?? NSRange(location: 0, length: self.length)
let subRange = range(of: searchString, options: options, range: searchRange)
if subRange.location != NSNotFound {
let nextRangeStart = subRange.location + subRange.length
let nextRange = NSRange(location: nextRangeStart, length: searchRange.location + searchRange.length - nextRangeStart)
return [subRange] + ranges(of: searchString, options: options, searchRange: nextRange)
} else {
return []
}
}
}
/// All ranges using String and Range<Index>
/// Is usually used together with NSAttributedString
extension String {
public func ranges(of searchString: String, options: CompareOptions = [], searchRange: Range<Index>? = nil) -> [Range<Index>] {
if let range = range(of: searchString, options: options, range: searchRange, locale: nil) {
let nextRange = range.upperBound..<(searchRange?.upperBound ?? endIndex)
return [range] + ranges(of: searchString, searchRange: nextRange)
} else {
return []
}
}
}
Jeśli dobrze rozumiem dokumentację, dałoby to zakres dowolnych znaków w zestawie. Ale potrzebuję liczby * każdego * znaku. – Elliot
moim pomysłem jest utrzymanie słownika char -> liczba par, a następnie pobranie znaku w danym indeksie i zwiększenie jego liczby w słowniku ... lub po prostu powtórzenie ciągu znaków i sprawdzenie, czy każda postać jest w twoim zestawie, jeśli to jest przyrost, który się liczy – stefanB