Parsing strings that were saved to a text file - objective-c

I save pieces of data from my Cocoa application into a text file. The text file contains information as shown:
foo1 -> foo2
blah -> lwjef
hi -> bye
hello -> goodbye
Now the first part of each row is given by the user, but I need to get the part of each row after the ->. For example, if the user enters foo1, I want to output foo2 after parsing the text file. Does anyone know how to do this?

Parse once:
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSArray *lines = [string componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]];
for (NSString *line in lines) {
NSArray *values = [line componentsSeparatedByString:#" -> "];
if ([values count] != 2) {
continue;
}
[dictionary setObject:[values objectAtIndex:1] forKey:[values objectAtIndex:0]];
}
Then query for keys:
NSString *input = #"foo1";
NSString *answer = [dictionary objectForKey:input]; //#"foo2"
However, if the data originally came from your own application in the first place you should probably do this, instead of a custom (and insecure) string format:
//For saving:
[dictionary writeToFile:filePath atomically:YES];
//For loading:
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];

Related

delete capitalized items from NSArray

I have an NSArray that contains a bunch of strings. Some of the items in the NSArray are capitalized; some are not. I want to delete all of the items that are capitalized from the NSArray.
My code is below. If you have a mac, you can run this code, since all macs come loaded with the file I am loading into the NSArray.
// Read in a file as a huge string (ignoring the possibility of an error)
NSString *wordString = [NSString stringWithContentsOfFile:#"/usr/share/dict/words" encoding:NSUTF8StringEncoding error:NULL];
// Break it into an array of strings
NSArray *words = [wordString componentsSeparatedByString:#"\n"];
for example, if my NSArray contains the following two items ['wolf','Wolf'] I want Wolf to be deleted.
Here's one way. Not necessarily the best/fastest:
NSCharacterSet *uppercaseSet = [NSCharacterSet uppercaseLetterCharacterSet];
NSMutableArray *itemsToDelete = [NSMutableArray new];
for ( NSString *word in words ) {
if ( (word.length > 0) && [uppercaseSet characterIsMember:[word characterAtIndex:0]] )
[itemsToDelete addObject:word];
}
NSMutableArray *newArray = [words mutableCopy];
[newArray removeObjectsInArray:itemsToDelete];
After looking at the code above, I realized the code below would be much faster. Turns out to be about 40x faster because it's not deleting items from an array, just appending them, which is a faster operation:
NSCharacterSet *uppercaseSet = [NSCharacterSet uppercaseLetterCharacterSet];
NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:words.count];
for ( NSString *word in words ) {
if ( (word.length > 0) && ![uppercaseSet characterIsMember:[word characterAtIndex:0]] )
[newArray addObject:word];
}

iOS - Most efficient way to find word occurrence count in a string

Given a string, I need to obtain a count of each word that appears in that string. To do so, I extracted the string into an array, by word, and searched that way, but I have the feeling that searching the string directly is more optimal. Below is the code that I originally wrote to solve the problem. I'm up for suggestions on better solutions though.
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);
Example:
Starting string:
"This is a test. This is only a test."
Results:
"This" - 2
"is" - 2
"a" - 2
"test" - 2
"only" - 1
This is exactly what an NSCountedSet is for.
You need to break the string apart into words (which iOS is nice enough to give us a function for so that we don't have to worry about punctuation) and just add each of them to the counted set, which keeps track of the number of times each object appears in the set:
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])
If I had to guess, I would say NSRegularExpression for that. Like this:
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string
options:0
range:NSMakeRange(0, [string length])];
That snippet was taken from here.
Edit 1.0:
Based on what Sir Till said:
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];
}
}
You should be careful with:
Punctuation signs. (near other words)
UpperCase words vs lowerCase words.
I think that's really bad idea that you trying to search a words among the long paragraph with a loop. You should use a regular expression to do that! I know it's not easy at first time to learn it but it's really worth to know it! Take look at this case Use regular expression to find/replace substring in NSString

all Keys and Objects from a NSDictionary to a NSString

I've got a NSDictionary and I'd like put all of it's objects and keys into a NSString, so that I can finally display them in a label like this:
key1: object1
key2: object2
key3: object3
... ...
Any ideas?
Build the string and then set it to the labels text.
NSMutableString *myString = [[NSMutableString alloc] init];
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[myString appendFormat:#"%# : %#\n", key, obj];
}];
self.label.text = myString;
Note
The docs (String Programming Guide) for the %# format specifier state:
%#
Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function.
So if these are your own custom objects in the dictionary you will most likely need to override the description method to provide more meaningful output
Update
You mention that you need your output sorted by keys - dictionaries are not ordered so you will have to do it differently - this example assumes that your keys are strings
NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSMutableString *myString = [[NSMutableString alloc] init];
for (NSString *key in sortedKeys) {
[myString appendFormat:#"%# : %#\n", key, [dictionary objectForKey:key]];
}
self.label.text = myString;
try this
for(id key in [dictionary allKeys])
{
id value = [dictionary objectForKey:key];
NSLog(#"%# : %#", key, value);
}
NSString *row;
for (id key in dictionary) {
row = [NSString stringWithFormat:"%#: %#", key, [dictionary objectForKey:key]];
// do something with your row string
}
Iam trying to append two time values from my TCTime object and display in label, even though I added "\n" towards the end it is printing only the first value but not the second value.
_feedTimes is NSArray.
NSMutableString *myString = [[NSMutableString alloc] init];
TCTime *time = _feedTimes[indexPath.row];
[myString appendFormat:#"%s : %#\n", "Time 1 ", time.Time1];
[myString appendFormat:#"%s : %#\n", "Time 2 ", time.Time2];
self.label.text = myString;

NSDictionary - List all

In a NSMutableDictionary like this:
[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithString:firstName], #"NAME",
[NSNumber numberWithFloat:familyName], #"SURNAME",
nil];
How can all of its elements be converted to the NSString? with the requirement that names and surnames are arranged in string like this: "name, surname, name, surname..."?
This gives a string with all the names but not surnames:
NSString * result = [[urlArray valueForKey:#"NAME"] componentsJoinedByString:#", "];
Is there a way similar to the one above to create a string with all the values of NSMutableDictionary?
Try something like this:
NSString *result = [NSString stringWithFormat:#"%#, %#", [urlArray valueForKey:#"SURNAME"], [urlArray valueForKey:#"NAME"]];
The %# represents an objective-c object for more details see the Apple docs
The code to make a NSString from an NSDictionary may look like (if you're trying to print out everything in the NSDictionary)
NSMutableString* mutableString = [NSMutableString string];
NSDictionary* dictionary;
for(NSString* key in [dictionary allKeys])
{
[mutableString appendString:[[dictionary objectForKey:key] description]];
}

Contents of file as input to hashtable in Objective-C

I know to read the contents of file in Objective-C, but how to take it as the input to hashtable.
Consider the contents of text file as test.txt
LENOVA
HCL
WIPRO
DELL
Now i need to read this into my Hashtable as Key value pairs
KEY VAlue
1 LENOVA
2 HCL
3 WIPRO
4 DELL
You want to parse your file into an array of strings and assign each element in this array with a key. This may help you get in the right direction.
NSString *wholeFile = [NSString stringWithContentsOfFile:#"filename.txt"];
NSArray *lines = [wholeFile componentsSeparatedByString:#"\n"];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:[lines count]];
int counter = 1;
for (NSString *line in lines)
{
if ([line length])
{
[dict setObject:line forKey:[NSString stringWithFormat:"%d", counter]];
// If you want `NSNumber` as keys, use this line instead:
// [dict setObject:line forKey:[NSNumber numberWithInt:counter]];
counter++;
}
}
Keep in mind this isn't the most efficient method of parsing your file. It also uses the deprecated method stringWithContentsOfFile:.
To get the line back, use:
NSString *myLine = [dict objectForKey:#"1"];
// If you used `NSNumber` class for keys, use:
// NSString *myLine = [dict objectForKey:[NSNumber numberWithInt:1]];