I want to parse a csv file into a table view in Iphone.
I have a csv file with latitude and longtitude and date in the following format.
-37.6704090666667;144.852821866667;2010-07-12 09:34:18
-37.6784624166667;144.867258566667;2010-07-12 09:35:18
-37.6886946666667;144.880478666667;2010-07-12 09:36:18
-37.71000224;144.89458948;2010-07-12 09:37:22
I would like to put the above data in a table where the latitude and the longtitude is in bold separated by a comma and the date below it in smaller lighter font. On clicking this i am taking it into the map with the pointer. I know how to do this but i would like to know how to put the data in the csv file in a table view. And also once i put this data into a table view, i would like to know how to check for invalid coordinates in the entire csv file ?
You can use a wonderful library for CSV Parsing
https://github.com/davedelong/CHCSVParser
Try it. It is simple
For the coordiane validation, you can simply include a checking.
The latitude ranges in between -90 to +90. Longitude lies between -180 to +180. Include a simple validation for this
Try this way...
path1 = [[NSString alloc] initWithContentsOfFile:CSVPath encoding:NSUTF8StringEncoding error:&error];
path1=[path1 stringByReplacingOccurrencesOfString:#"\r" withString:#""];
NsArray* messArr=[path1 componentsSeparatedByString:#"\n"];
//MessArr gives the all row from CSV FIle
for(i=1;i<[messArr count]-1;i++)
{
d=[[NSMutableDictionary alloc] init];
StrValue=[NSString stringWithFormat:#"%#",[messArr objectAtIndex:i]];
StrValue=[StrValue stringByReplacingOccurrencesOfString:#"\"" withString:#""];
StrValue=[StrValue stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// Here give whatever saperator you need to saperate data
arr=[StrValue componentsSeparatedByString:#";"];
// This arr gives you the all threee data mean lat,long, & date
}
Related
After finally figuring out how to pull data from google spreadsheets, I can't understand how to add new entries to the end of file.
Here's what I want to achieve:
My app should send some survey results to a google spreadsheet, here's how the file is supposed to look:
Let's assume that I need to send the next survey results to that spreadsheet. How do I send them and make sure that they appear just under the last survey results?
Thanks
UPDATE
I've found an answer long ago, so decided to update the question for lone rangers like me that couldn't find any info on this topic :)
For this answer I assume that you already know how to get to the spreadsheet's cells feed.
Here's what you need to do after you get the cells feed:
First of all we need to find out the last row number so we can later on write to the row under it.
NSArray * entries = [cellsFeed entries]; // we pull out all the entries from the feed
GDataEntrySpreadsheetCell * lastCell = [entries lastObject]; // then we take just the last one
NSString * title = [[lastCell title] stringValue]; // then we need it's title. The cells title is a combination of the column letter and row number (ex: A20 or B5)
NSString * lastRow = [[title componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:#""]; // then we remove the letters and we're left only with the row number
We can now send some data to the row under the last row like this:
// create a cell object and give it the row number (in our case it's the row under lastRow, so we add + 1), column number (yes, here you should provide a number and not a letter) and the string that you want to appear in the cell
GDataSpreadsheetCell * cell = [GDataSpreadsheetCell cellWithRow:[lastRow intValue] + 1 column:1 inputString:#"some value" numericValue:nil resultString:nil];
// create a cellEntry object that will contain the cell
GDataEntrySpreadsheetCell * cellEntry = [GDataEntrySpreadsheetCell spreadsheetCellEntryWithCell:cell];
// upload the cellEntry to your spreadsheet
[_srv fetchEntryByInsertingEntry:cellEntry
forFeedURL: [[workSheet cellsLink] URL] // make sure that you save the workSheet feed in an instance variable so that you'll be able to reach it in another method. If you pulled data from the spreadsheet that you must already know how to get the worksheet feed
delegate:self
didFinishSelector:nil];
That's it! The data should upload to your spreadsheet.
Let me know if you have any questions, I know the documentation is kinda scarce for this.
I have a long string I want to retrieve from a URL and store at app launch. Later, I want to insert individual values into that string.
I'd like to do something like this:
NSString *numberLine = #"1 %# 3 %# 5 %#";
//... (later) ...
NSString *final = [NSString stringWithFormat:numberLine, #"two", #"four", #"six"];
NSLog(#"%#", final); //Should output "1 two 3 four 5 six"
I want the #"two" to be inserted into the placeholder %# that was earlier saved into numberLine.
Is there a good way to accomplish something like this?
So far my only thought is to do something like:
NSString *script = #"width = PLACEHOLDERpx";
script = [script stringByReplacingOccurrencesOfString:#"PLACEHOLDER" withString:#"12"];
What you are describing is a template. You want to leave placeholders in a string that will be filled out with data. While you could use %# and %d through a string that gets difficult as the string grows more complex. You may want to use a template library like Mustache for Objective-C. This will let you write expressions like this:
Hello {{SomeVariable}}
All you have to do is pass in an NSDictionary with keys that correspond to the data you want to render. So for the example above you might do the following:
NSString *result = [GRMustacheTemplate renderObject:[NSDictionary dictionaryWithObject:#"World" forKey:#"SomeVariable"];
fromString:#"Hello {{SomeVariable}}"
error:NULL];
This will produce a result string Hello World.
I got a UITextView with an arbitrary length text (up to 10000 characters). I need to parse this text, extract all keywords and list them by the frequency of use with the most frequently used word being on top, next one down, etc. I will most likely present a modal UITableView after the operation is completed.
I'm thinking of an efficient and useful way to do this. I can try to separate a string using a delimiter in the form of [whitespace, punctuation marks, etc].
This gets me an array of character sequences.
I can add each add sequence as an NSMutableDictionary key, and increment its count once I see another instance of that word. However, this may result in a list of 300-400 words, most having frequency of 1.
Is there a good way to implement the logic that I'm describing? Should I try to sort the array in alphabetical order and try some kind of "fuzzy" logic match? Are there any NSDataDetector or NSString methods that can do this kind of work for me?
An additional question is: how would I extract stuff like a, at, to, for, etc, and do not list them in my keyword list?
It would be great if I can take a look at a sample project that has already accomplished this task.
Thank you!
You can use CFStringTokenizer to get the word boundaries. For counting, you could use an NSMutableDictionary, as you suggested, or an NSCountedSet, which might be slightly more efficient.
If you're not interested in words that have a frequency of 1 (or some other threshold), you would have to filter them out after counting all the words.
For ignoring certain words (a, the, for...), you need a word list specific to the language of your text. The Wikipedia article on stop words contains a couple of links, e.g. this CSV file.
There are many approaches to do this.
You should definitely add all your Keywords to an array (or other collection object) and reference it/ iterate through it so you are searching for these keywords and only these keywords (and are avoiding checking for occurrences of a, at, to, for, etc.)
NSArray *keywords = [ add your keywords ];
NSString *textToSearchThrough = #" your text "; // or load your text File here
- loop control statement here (like maybe fast enumerate), and inside this loop:
NSRange range = [textToCheckThrough rangeOfString:keywords[currentKeyword]
options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound) {
// meaning, you did find it
// add it to a resultsArray, add 1 to this keyword's occurrenceCounter (which you must also declare and keep track of)
// etc.
}
Then you loop through your results array, check number of occurrences per keyword, purge those who's occurrence count is < minOccurrenceCount, and sort remaining from highest to lowest.
I ended up going with the CFStringTokenizer . I'm not sure if the bridged casts below are correct, but it seems to work
-(void)listAllKeywordsInString:(NSString*)text
{
if(text!=nil)
{
NSMutableDictionary* keywordsDictionary = [[NSMutableDictionary alloc] initWithCapacity:1024];
NSString* key = nil;
NSLog(#"%#",text);
NSLog(#"Started parsing: %#",[[NSDate date] description]);
CFStringRef string =(__bridge CFStringRef)text; // Get string from somewhere
CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, (__bridge_retained CFStringRef) text, CFRangeMake (0,CFStringGetLength((__bridge_retained CFStringRef)text)), kCFStringTokenizerUnitWord, CFLocaleCopyCurrent());
unsigned tokensFound = 0; // or the desired number of tokens
CFStringTokenizerTokenType tokenType = kCFStringTokenizerTokenNone;
while(kCFStringTokenizerTokenNone != (tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) ) {
CFRange tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer);
CFStringRef tokenValue = CFStringCreateWithSubstring(kCFAllocatorDefault, string, tokenRange);
// This is the found word
key =(__bridge NSString*)tokenValue;
//increment its count
NSNumber* count = [keywordsDictionary objectForKey:key];
if(count!=nil)
{
[keywordsDictionary setValue:[NSNumber numberWithInt:1] forKey:key];
}else {
[keywordsDictionary setValue:[NSNumber numberWithInt:count.intValue+1] forKey:key];
}
CFRelease(tokenValue);
++tokensFound;
}
NSLog(#"Ended parsing. tokens Found: %d, %#",tokensFound,[[NSDate date] description]);
NSLog(#"%#",[keywordsDictionary description]);
// Clean up
CFRelease(tokenizer);
}
}
Can someone give a code example of how to right pad an NSString in objective-c please?
For example want these strings:
Testing 123 Long String
Hello World
Short
if right padded to a column width of say 12: and then a sting "XXX" is added to the end of each, it would give:
Testing 123 xxx
Hello World xxx
Short xxx
That is a 2nd column would like up.
Adam is on the right track, but not quite there. You do want to use +stringWithFormat:, but not quite as he suggested. If you want to pad "someString" to (say) a minimum of 12 characters, you'd use a width specifier as part of the format. Since you want the result to be left-justified, you need to precede the width specifier with a minus:
NSString *padded = [NSString stringWithFormat:#"%-12#", someString];
Or, if you wanted the result to be exactly 12 characters, you can use both minimum and maximum width specifiers:
NSString *padded = [NSString stringWithFormat:#"%-12.12#", someString];
2nd column of what would line up?
Given that you are on iOS, using HTML or a table view would be far more straightforward than trying to line up characters with spaces. Beyond being programmatically more elegant, it will look better, be more resilient to input data changes over time, and render a user experience more in line with expectations for the platform.
If you really want to use spaces, then you are going to have to limit your UI to a monospace font (ugly for readability purposes outside of specific contexts, like source code) and international characters are going to be a bit of a pain.
From there, it would be a matter of getting the string length (keeping in mind that "length" does not necessarily mean "# of characters" in some languages), doing a bit of math, using substringWithRange: and appending spaces to the result.
Unfortunately, Objective-C does not allow format specifiers for %#. A work-around for padding is the following:
NSString *padded = [NSString stringWithFormat:#"%#%*s", someString, 12-someString.length, ""];
which will pad the string to the right with spaces up to a field length of 12 characters.
%-# does not work, but %-s works
NSString *x = [NSString stringWithFormat:#"%-3#", #"a" ];
NSString *y = [NSString stringWithFormat:#"%-3#", #"abcd" ];
NSString *z = [NSString stringWithFormat:#"%-3# %#", #"a", #"bc" ];
NSString *zz = [NSString stringWithFormat:#"%-3s %#", "a", #"bc" ];
NSLog(#"[%#][%#][%#][%#].......", x,y,z,zz);
output:
[a][abcd][a bc][a bc].......
Try below. its working for me.
NSString *someString = #"1234";
NSString *padded = [someString stringByPaddingToLength: 16 withString: #"x" startingAtIndex:0];
NSLog(#"%#", someString);
NSLog(#"%#", padded);
First up, you're doing this a bad way. Please use separate labels for your two columns and then you will also be able to use proportional fonts. The way you're going about it you should be looking for an iPhone curses library.
If you really have to do it this way just use stringWithFormat:, like:
NSString *secondColumnString = #"xxx";
NSString *spacedOutString = [NSString stringWithFormat:#"testingColOne %#", secondColumnString];
NSString *spacedOutString = [NSString stringWithFormat:#"testingAgain %#", secondColumnString];
I have one array and it contains the date strings. I want to compare the date strings and displayed the date string as grouping, so it should display the date as only once, when duplicate date as found.
My array
NSMutableArray *arr = [[NSMutableArray alloc] initWithObjects:#"2010-12-28 04:23:47",
#"2010-12-28 04:21:50",
#"2010-12-28 04:18:56",
#"2010-12-27 13:39:18",
#"2010-12-22 21:48:09",
#"2010-12-22 20:44:18",
#"2010-12-22 20:25:26",
#"2010-12-22 20:08:39",nil];
Expected Output is,
"2010-12-28 "
"2010-12-27 "
"2010-12-22 ".
When compared to the date string, the time is not a problem, i want to display the date wise only(Grouping date).
Please help me out.
THanks.
Code as follows,
NSMutableArray *filterdArray=[[NSMutableArray alloc]init];
for(NSString *string in arr)
{
NSArray *components = [string componentsSeparatedByString: #" "];
//Check that date is present in filterdArray
//if not present
//add the value to array using
[filterdArray addObject:[components objectAtIndex:0]];
}
Then sort the values in filterdArray