find numbers in text file objective-c [duplicate] - objective-c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to generate all of the numbers of pi in Objective-C
I want to implement "am i in pi" for searching birth date in pi numbers,
I have 1 million series of pi Numbers in .txt file, would you please give me some hints for implement this game?
what is the best way? how can I found my birth date in text file?
Thanks in advance

NSString* str = [NSString stringWithContentsOfFile: #"path to your file" encoding: NSASCIIStringEncoding error: nil];
NSRange rng = [str rangeOfString: #"1989"]; //here is the range of the birth year 1989

1 megabyte is sufficiently small that loading and then scanning it is reasonably straightforward. If you wanted to be a little clever, you could map the file into memory and then scan it through the map (avoiding the need to load the entire file into memory, which becomes more important for multi-hundred-MB files).
NSDataReadingOptions options = NSDataReadingMappedIfSafe | NSDataReadingUncached;
NSData *data = [NSData dataWithContentsOfFile:filename
options:options
error:nil];
NSString *string = [[NSString alloc] initWithData:data
encoding:NSASCIIStringEncoding];
NSRange range = [string rangeOfString:year];
[string release];
You could add appropriate error handling.

Once I wrote a category of NSString, which has method:
- (NSArray *)occurrencesOfSubstring:(NSString *)string
{
NSMutableArray *result = [NSMutableArray array];
NSRange range = NSMakeRange(0, self.length);
NSUInteger len = self.length;
while (range.location != NSNotFound) {
range = [self rangeOfString:string options:0 range:range];
if (range.location != NSNotFound) {
NSRange resRange = range;
[result addObject:[NSValue valueWithRange:resRange]];
range = NSMakeRange(NSMaxRange(resRange), len - NSMaxRange(resRange));
}
}
return result;
}
It returns array of ranges of searched substring. Hope it helps.

Related

Take all numbers separated by spaces from a string and place in an array

I have a NSString formatted like this:
"Hello world 12 looking for some 56"
I want to find all instances of numbers separated by whitespace and place them in an NSArray. I dont want to remove the numbers though.
Whats the best way of achieving this?
This is a solution using regular expression as suggested in the comment.
NSString *string = #"Hello world 12 looking for some 56";
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:#"\\b\\d+" options:nil error:nil];
NSArray *matches = [expression matchesInString:string options:nil range:(NSMakeRange(0, string.length))];
NSMutableArray *result = [[NSMutableArray alloc] init];
for (NSTextCheckingResult *match in matches) {
[result addObject:[string substringWithRange:match.range]];
}
NSLog(#"%#", result);
First make an array using NSString's componentsSeparatedByString method and take reference to this SO question. Then iterate the array and refer to this SO question to check if an array element is number: Checking if NSString is Integer.
I don't know where you are looking to do perform this action because it may not be fast (such as if it's being called in a table cell it may be choppy) based upon the string size.
Code:
+ (NSArray *)getNumbersFromString:(NSString *)str {
NSMutableArray *retVal = [NSMutableArray array];
NSCharacterSet *numericSet = [NSCharacterSet decimalDigitCharacterSet];
NSString *placeholder = #"";
unichar currentChar;
for (int i = [str length] - 1; i >= 0; i--) {
currentChar = [str characterAtIndex:i];
if ([numericSet characterIsMember:currentChar]) {
placeholder = [placeholder stringByAppendingString:
[NSString stringWithCharacters:&currentChar
length:[placeholder length]+1];
} else {
if ([placeholder length] > 0) [retVal addObject:[placeholder intValue]];
else placeholder = #"";
return [retVal copy];
}
To explain what is happening above, essentially I am,
going through every character until I find a number
adding that number including any numbers after to a string
once it finds a number it adds it to an array
Hope this helps please ask for clarification if needed

Get a substring from an NSString until arriving to any letter in an NSArray - objective C

I am trying to parse a set of words that contain -- first greek letters, then english letters. This would be easy if there was a delimiter between the sets.That is what I've built so far..
- (void)loadWordFileToArray:(NSBundle *)bundle {
NSLog(#"loadWordFileToArray");
if (bundle != nil) {
NSString *path = [bundle pathForResource:#"alfa" ofType:#"txt"];
//pull the content from the file into memory
NSData* data = [NSData dataWithContentsOfFile:path];
//convert the bytes from the file into a string
NSString* string = [[NSString alloc] initWithBytes:[data bytes]
length:[data length]
encoding:NSUTF8StringEncoding];
//split the string around newline characters to create an array
NSString* delimiter = #"\n";
incomingWords = [string componentsSeparatedByString:delimiter];
NSLog(#"incomingWords count: %lu", (unsigned long)incomingWords.count);
}
}
-(void)parseWordArray{
NSLog(#"parseWordArray");
NSString *seperator = #" = ";
int i = 0;
for (i=0; i < incomingWords.count; i++) {
NSString *incomingString = [incomingWords objectAtIndex:i];
NSScanner *scanner = [NSScanner localizedScannerWithString: incomingString];
NSString *firstString;
NSString *secondString;
NSInteger scanPosition;
[scanner scanUpToString:seperator intoString:&firstString];
scanPosition = [scanner scanLocation];
secondString = [[scanner string] substringFromIndex:scanPosition+[seperator length]];
// NSLog(#"greek: %#", firstString);
// NSLog(#"english: %#", secondString);
[outgoingWords insertObject:[NSMutableArray arrayWithObjects:#"greek", firstString, #"english",secondString,#"category", #"", nil] atIndex:0];
[englishWords insertObject:[NSMutableArray arrayWithObjects:secondString,nil] atIndex:0];
}
}
But I cannot count on there being delimiters.
I have looked at this question. I want something similar. This would be: grab the characters in the string until an english letter is found. Then take the first group to one new string, and all the characters after to a second new string.
I only have to run this a few times, so optimization is not my highest priority.. Any help would be appreciated..
EDIT:
I've changed my code as shown below to make use of NSLinguisticTagger. This works, but is this the best way? Note that the interpretation for english characters is -- for some reason "und"...
The incoming string is: άγαλμα, το statue, only the last 6 characters are in english.
int j = 0;
for (j=0; j<incomingString.length; j++) {
NSString *language = [tagger tagAtIndex:j scheme:NSLinguisticTagSchemeLanguage tokenRange:NULL sentenceRange:NULL];
if ([language isEqual: #"und"]) {
NSLog(#"j is: %i", j);
int k = 0;
for (k=0; k<j; k++) {
NSRange range = NSMakeRange (0, k);
NSString *tempString = [incomingString substringWithRange:range ];
NSLog (#"tempString: %#", tempString);
}
return;
}
NSLog (#"Language: %#", language);
}
Alright so what you could do is use NSLinguisticTagger to find out the language of the word (or letter) and if the language has changed then you know where to split the string. You can use NSLinguisticTagger like this:
NSArray *tagschemes = #[NSLinguisticTagSchemeLanguage];
NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:tagschemes options: NSLinguisticTagPunctuation | NSLinguisticTaggerOmitWhitespace];
[tagger setString:#"This is my string in English."];
NSString *language = [tagger tagAtIndex:0 scheme:NSLinguisticTagSchemeLanguage tokenRange:NULL sentenceRange:NULL];
//Loop through each index of the string's characters and check the language as above.
//If it has changed then you can assume the language has changed.
Alternatively you can use NSSpellChecker's requestCheckingOfString to get teh dominant language in a range of characters:
NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
[spellChecker setAutomaticallyIdentifiesLanguages:YES];
NSString *spellCheckText = #"Guten Herr Mustermann. Dies ist ein deutscher Text. Bitte löschen Sie diesen nicht.";
[spellChecker requestCheckingOfString:spellCheckText
range:(NSRange){0, [spellCheckText length]}
types:NSTextCheckingTypeOrthography
options:nil
inSpellDocumentWithTag:0
completionHandler:^(NSInteger sequenceNumber, NSArray *results, NSOrthography *orthography, NSInteger wordCount) {
NSLog(#"dominant language = %#", orthography.dominantLanguage);
}];
This answer has information on how to detect the language of an NSString.
Allow me to introduce two good friends of mine.
NSCharacterSet and NSRegularExpression.
Along with them, normalization. (In Unicode terms)
First, you should normalize strings before analyzing them against a character set.
You will need to look at the choices, but normalizing to all composed forms is the way I would go.
This means an accented character is one instead of two or more.
It simplifies the number of things to compare.
Next, you can easily build your own NSCharacterSet objects from strings (loaded from files even) to use to test set membership.
Lastly, regular expressions can achieve the same thing with Unicode Property Names as classes or categories of characters. Regular expressions could be more terse but more expressive.

how to get a range to text near a specific word in a NSString?

I have a long NSString e.g. "For performance reasons, a table view data source generally reuses UITableViewCell objects. The table view maintains a queue of cell objects that are marked for reuse. For example, if you were displaying a list that contained a 1000 rows it would be highly inefficient to create 1000 table view cells, whereas a lot of more effective to create the few currently in view."
Now if user search for word "maintains" then above NSString definitely have this word.. now i just want to show only rand of line with this word, not whole text. So the use will know that this text have this word and where it is.
-User search for "maintains".
-code process the NSString.
-Output will look like this.. "table view maintains a queue of cell objects that..." or this can be also a result.. "maintains a queue of cell objects that..."
2nd result would be great...
NSRange range = [myString rangeOfString:#"maintains" options:NSBackwardsSearch range:NSMakeRange(0, 11)];
NSLog(#"range.location: %lu", range.location);
NSString *substring = [myString substringFromIndex:range.location+1];
NSLog(#"substring: '%#'", substring);`
but no success...from this CODE
Please help me to get my target...
This will do it:
- (NSString *)getSnippetContaining:(NSString *)keyword
inString:(NSString *)theString
numberOfWords:(NSUInteger)wordCount
{
NSRange range = [theString rangeOfString:keyword
options:NSBackwardsSearch
range:NSMakeRange(0, theString.length)];
if (range.location == NSNotFound) {
return nil;
}
NSString *substring = [theString substringFromIndex:range.location];
NSArray *words = [substring componentsSeparatedByString:#" "];
if (wordCount > words.count) {
wordCount = words.count;
}
NSArray *snippetWords = [words subarrayWithRange:NSMakeRange(0, wordCount)];
NSString *snippet = [snippetWords componentsJoinedByString:#" "];
return snippet;
}
numberOfWords is the length of the snippet you wish to extract from the input.

Extracting sentences containing keywords objective c

I have a block of text (a newspaper article if it's of any relevance) was wondering if there is a way to extract all sentences containing a particular keyword in objective-c? I've been looking a bit at ParseKit but aren't having much luck!
You can enumerate sentences using native NSString methods like this...
NSString *string = #"your text";
NSMutableArray *sentences = [NSMutableArray array];
[string enumerateSubstringsInRange:NSMakeRange(0, string.length)
options:NSStringEnumerationBySentences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
//check that this sentence has the string you are looking for
NSRange range = [substring rangeOfString:#"The text you are looking for"];
if (range.location != NSNotFound) {
[sentences addObject:substring];
}
}];
for (NSString *sentence in sentences) {
NSLog(#"%#", sentence);
}
At the end you will have an array of sentences all containing the text you were looking for.
Edit: As noted in the comments there are some inherit weaknesses with my solution as it requires a perfectly formatted sentence where period + space is only used when actually ending sentences... I'll leave it in here as it could be viable for people sorting a text with another (known) separator.
Here's another way of achieving what you want:
NSString *wordYouAreLookingFor = #"happy";
NSArray *arrayOfSentences = [aString componentsSeparatedByString:#". "]; // get the single sentences
NSMutableArray *sentencesWithMatchingWord = [[NSMutableArray alloc] init];
for (NSString *singleSentence in arrayOfSentences) {
NSInteger originalSize = [singleSentence length];
NSString *possibleNewString = [singleSentence stringByReplacingOccurrencesOfString:wordYouAreLookingFor withString:#""];
if (originalSize != [possibleNewString length]) {
[sentencesWithMatchingWord addObject:singleSentence];
}
}

Objective-C, rangeOfString from an offset

is it possible to use the method rangeOfString to search for a NSString starting from a given offset?
Something more similar to the strpos function in PHP.
Thanks
Not -rangeOfString:, but a similar method - -rangeOfString:options:range:.
(Edit: An example)
NSString *string = #"YaddaYaddaYadda";
NSString *searchString = #"Yadda";
NSRange thisCharRange, searchCharRange;
searchCharRange = NSMakeRange(3, [string length]);
thisCharRange = [string rangeOfString:searchString options:0 range:searchCharRange];
NSLog(#"thisCharRange: %#", NSStringFromRange(thisCharRange));
I find a problem with the example up there. It'll cause "Range or index out of bounds".
searchCharRange = NSMakeRange(3, [string length]);
should change to
searchCharRange = NSMakeRange(3, [string length] - 3);
that is,the range's length should not be longer than the original string's length - the range's start location.