How to Read CSV with comma placed within double quotes - ios

I am implementing csv splitting in my project . can I know how to implement CSV splitting in ios. say for example i have a string #"one,\"two,three\",four" . I need output as below in an array format which containts 3 element
one
two,three
four

You can use this code but, it is not proper way:
NSString *StrDataOfCSV=#"one,\"two,three\",four";
NSMutableArray * csvArray= [[NSMutableArray alloc]init];
NSArray * firstSeparated=[StrDataOfCSV componentsSeparatedByString: #"\","];
for (NSString * strCom in firstSeparated) {
NSArray * arrCom=[strCom componentsSeparatedByString:#",\""];
[csvArray addObjectsFromArray:arrCom];
}

Something like this to "normalize" your input string, replacing the commas with a new separator character, one that you can guarantee won't appear in your input (e.g. a |), and removing the quotes from the quoted fields:
char *cbCSVRecord = "one,\"two,three\",four";
bool bQuotedField = false;
// normalize
for (int i = 0,j = 0;i < (int)strlen(cbCSVRecord);i++)
{
if ((cbCSVRecord[i] == '\n') || (cbCSVRecord[i] == '\r'))
cbCSVRecord[i] = '\0';
// Not a double quote?
if (cbCSVRecord[i] != '"')
{
// if a comma NOT within a quoted field, replace with a new separator
if ((cbCSVRecord[i] == ',') && (!bQuotedField))
cbCSVRecord[i] = '|';
// new output
cbCSVRecord[j] = cbCSVRecord[i];
j++;
}
// Is a double quote, toggle bQuotedField
else
{
if (!bQuotedField)
bQuotedField = true;
else
bQuotedField = false;
}
}
cbCSVRecord[j] = '\0';
please note that I roughed out this code, and it is plain C code. It should either work or have you pretty close.
An input of #"one,\"two,three\",four" should become #"one|two,three|four", and you can then use:
NSArray *listItems = [list componentsSeparatedByString:#"|"];

Use NSString's componentsSeparatedByString:
NSString *list = #"Karin, Carrie, David";
NSArray *listItems = [list componentsSeparatedByString:#", "];

Related

custom NSExpression functions like sin(x)

I know how to add custom functions to NSNumber for NSExpression to work with it. But for use it i need to declarate a string like "FUNCTION(1, 'sin')". Is is any way to declarate it just like "sin(1)"?
No, you cannot extend the syntax understood by NSExpression(format:).
For advanced expression parsing and evaluating, use 3rd party solutions
such as DDMathParser.
The selected answer is, in my opinion, ridiculous. You can, of course, simply reformat your string to your desired custom function, no need to become dependent on an entire library.
In your case, something like the following would work just fine.
NSString *equation = #"2+sin(54.23+(2+sin(sin(3+5))))-4+(5-3)+cos(4)";//your equation here
NSArray *functionNames = #[#"sin", #"cos", #"tan"];//your supported functions here
for (NSString *functionName in functionNames) {
NSString *functionPrefix = [NSString stringWithFormat:#"%#(", functionName];
while ([equation containsString:functionPrefix]) {
int parensLevel = 1;
int functionParameterIndex = ((int)[equation rangeOfString:functionPrefix].location)+((int)functionPrefix.length);
int characterIndex = functionParameterIndex;
while (characterIndex < equation.length) {
NSString *character = [equation substringWithRange:NSMakeRange(characterIndex, 1)];
if ([character isEqualToString:#"("]) {
parensLevel++;
} else if ([character isEqualToString:#")"]) {
parensLevel--;
}
if (parensLevel == 0) {
break;
}
characterIndex++;
}
if (parensLevel != 0) {
break;//parens weren't balanced, error handle as needed
}
NSString *functionParameter = [equation substringWithRange:NSMakeRange(functionParameterIndex, characterIndex-functionParameterIndex)];
NSString *function = [NSString stringWithFormat:#"%#(%#)", functionName, functionParameter];
equation = [equation stringByReplacingOccurrencesOfString:function withString:[NSString stringWithFormat:#"FUNCTION(%#,'%#')", functionParameter, functionName]];
}
}
//po string = "2+FUNCTION(54.23+(2+FUNCTION(FUNCTION(3+5,'sin'),'sin')),'sin')-4+(5-3)+FUNCTION(4,'cos')"
I wrote this in Objective-C but it works converted to swift as well.

Converting very large NSDecimal to string eg. 400,000,000,000 -> 400 T and so forth

I am making a game that requires me to use very large numbers. I believe I am able to store very large numbers with NSDecimal. However, when displaying the numbers to users I would like to be able to convert the large number to a succinct string that uses characters to signify the value eg. 100,000 -> 100k 1,000,000 -> 1.00M 4,200,000,000 -> 4.20B and so forth going up to extremely large numbers. Is there any built in method for doing so or would I have to use a bunch of
NSDecimalCompare statements to determine the size of the number and convert?
I am hoping to use objective c for the application.
I know that I can use NSString *string = NSDecimalString(&NSDecimal, _usLocale); to convert to a string could I then do some type of comparison on this string to get the result I'm looking for?
Use this method to convert your number into a smaller format just as you need:
-(NSString*) suffixNumber:(NSNumber*)number
{
if (!number)
return #"";
long long num = [number longLongValue];
int s = ( (num < 0) ? -1 : (num > 0) ? 1 : 0 );
NSString* sign = (s == -1 ? #"-" : #"" );
num = llabs(num);
if (num < 1000)
return [NSString stringWithFormat:#"%#%lld",sign,num];
int exp = (int) (log(num) / 3.f); //log(1000));
NSArray* units = #[#"K",#"M",#"G",#"T",#"P",#"E"];
return [NSString stringWithFormat:#"%#%.1f%#",sign, (num / pow(1000, exp)), [units objectAtIndex:(exp-1)]];
}
Some sample examples:
NSLog(#"%#",[self suffixNumber:#99999]); // 100.0K
NSLog(#"%#",[self suffixNumber:#5109999]); // 5.1M
Source
Solved my issue: Can only be used if you know that your NSDecimal that you are trying to format will only be a whole number without decimals so make sure you round when doing any math on the NSDecimals.
-(NSString *)returnFormattedString:(NSDecimal)nsDecimalToFormat{
NSMutableArray *formatArray = [NSMutableArray arrayWithObjects:#"%.2f",#"%.1f",#"%.0f",nil];
NSMutableArray *suffixes = [NSMutableArray arrayWithObjects:#"k",#"M",#"B",#"T",#"Qa",#"Qi",#"Sx",#"Sp",#"Oc",#"No",#"De",#"Ud",#"Dud",#"Tde",#"Qde",#"Qid",#"Sxd",#"Spd",#"Ocd",#"Nvd",#"Vi",#"Uvi",#"Dvi",#"Tvi", nil];
int dick = [suffixes count];
NSLog(#"count %i",dick);
NSString *string = NSDecimalString(&nsDecimalToFormat, _usLocale);
NSString *formatedString;
NSUInteger characterCount = [string length];
if (characterCount > 3) {
NSString *trimmedString=[string substringToIndex:3];
float a;
a = 100.00/(pow(10, (characterCount - 4)%3));
int remainder = (characterCount-4)%3;
int suffixIndex = (characterCount + 3 - 1)/3 - 2;
NSLog(#"%i",suffixIndex);
if(suffixIndex < [suffixes count]){
NSString *formatSpecifier = [formatArray[remainder] stringByAppendingString:suffixes[suffixIndex]];
formatedString= [NSString stringWithFormat:formatSpecifier, [trimmedString floatValue] / a];
}
else {
formatedString = #"too Big";
}
}
else{
formatedString = string;
}
return formatedString;
}

Truncate delimited NSString without removing delimiters

I have some data in an NSString, separated by colons:
#"John:Doe:1970:Male:Dodge:Durango"
I need to limit the total length of this string to 100 characters. But I also need to ensure the correct number of colons are present.
What would be a reasonable to way to truncate the string but also add the extra colons so I can parse it into the correct number of fields on the other side?
For example, if my limit was 18, you would end up with something like this:
#"John:Doe:1970:Ma::"
Here's an updated version of my own latest pass at this. Uses #blinkenlights algorithm:
+ (NSUInteger)occurrencesOfSubstring:(NSString *)substring inString:(NSString *)string {
// http://stackoverflow.com/a/5310084/878969
return [string length] - [[string stringByReplacingOccurrencesOfString:substring withString:#""] length] / [substring length];
}
+ (NSString *)truncateString:(NSString *)string toLength:(NSUInteger)length butKeepDelmiter:(NSString *)delimiter {
if (string.length <= length)
return string;
NSAssert(delimiter.length == 1, #"Expected delimiter to be a string containing a single character");
int numDelimitersInOriginal = [[self class] occurrencesOfSubstring:delimiter inString:string];
NSMutableString *truncatedString = [[string substringToIndex:length] mutableCopy];
int numDelimitersInTruncated = [[self class] occurrencesOfSubstring:delimiter inString:truncatedString];
int numDelimitersToAdd = numDelimitersInOriginal - numDelimitersInTruncated;
int index = length - 1;
while (numDelimitersToAdd > 0) { // edge case not handled here
NSRange nextRange = NSMakeRange(index, 1);
index -= 1;
NSString *rangeSubstring = [truncatedString substringWithRange:nextRange];
if ([rangeSubstring isEqualToString:delimiter])
continue;
[truncatedString replaceCharactersInRange:nextRange withString:delimiter];
numDelimitersToAdd -= 1;
}
return truncatedString;
}
Note that I don't think this solution handles the edge case from CRD where the number of delimiters is less than the limit.
The reason I need the correct number of colons is the code on the server will split on colon and expect to get 5 strings back.
You can assume the components of the colon separated string do not themselves contain colons.
Your current algorithm will not produce the correct result when one or more of the characters among the last colonsToAdd is a colon.
You can use this approach instead:
Cut the string at 100 characters, and store the characters in an NSMutableString
Count the number of colons, and subtract that number from the number that you need
Starting at the back of the string, replace non-colon characters with colons until you have the right number of colons.
I tend towards #dasblinkenlight, it's just an algorithm after all, but here's some code. Few modern shorthands - used an old compiler. ARC assumed. Won't claim it's efficient, or beautiful, but it does work and handles edge cases (repeated colons, too many fields for limit):
- (NSString *)abbreviate:(NSString *)input limit:(NSUInteger)limit
{
NSMutableArray *fields = [[input componentsSeparatedByString:#":"] mutableCopy];
NSUInteger colonCount = fields.count - 1;
if (colonCount >= limit)
return [#"" stringByPaddingToLength:limit withString:#":" startingAtIndex:0];
NSUInteger nonColonsRemaining = limit - colonCount;
for (NSUInteger ix = 0; ix <= colonCount; ix++)
{
if (nonColonsRemaining > 0)
{
NSString *fieldValue = [fields objectAtIndex:ix];
NSUInteger fieldLength = fieldValue.length;
if (fieldLength <= nonColonsRemaining)
nonColonsRemaining -= fieldLength;
else
{
[fields replaceObjectAtIndex:ix withObject:[fieldValue substringToIndex:nonColonsRemaining]];
nonColonsRemaining = 0;
}
}
else
[fields replaceObjectAtIndex:ix withObject:#""];
}
return [fields componentsJoinedByString:#":"];
}

creating a prefix NSString using two NSStrings

I have instructions to make a prefix method that takes two strings for each position where mask = 0 and the first string = second string up until these conditions are not meet that is your prefix NSString.
I made my attempt but for some reason my prefix string is returning as null and I was hoping i could get some help.
here is my method
- (void)prefixCalculation:(NSString *)seriesStart SeriesEnd:(NSString *)seriesEnd {
// call this method when loading the view to get everything set up
NSLog(#"start %#", seriesStart);
NSLog(#"end %#", seriesEnd);
// allocate values so you can use this to create the UITextField
seriesStartString = seriesStart;
seriesEndString = seriesEnd;
// set prefix string
for (int i = 0; i <= seriesStartString.length ; i++) {
unichar c1 = [seriesStartString characterAtIndex:i];
unichar c2 = [seriesEndString characterAtIndex:i];
if (c1 != c2) {
break;
}
else if (c1 == c2) {
NSString *str = [NSString stringWithFormat: #"%C", c1];
[prefixString appendFormat:#"%#",str];
}
}
NSLog(#"prefix %#", prefixString);
}
I am not sure what I am doing wrong but prefixString which is a NSMutableStrong comes back as null, any help would be greatly appreciated.
Since in your code you don't show the initialization of prefixString, I take a guess and suggest you to check whether you initialized it or not.
If that's not the case, prefixString is nil and sending messages to it will fail silently.

IOS: verify if a string is an empty string

is there a method to verify if a NSString haven't characters?
example of string without characters can be:
#"" or #" " or #"\n " or #"\n\n ", I want cosider these strings as empty strings and print a nslog that say me that these are emty, what kind of control I should use?
You can use this test:
if ([[myString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
// The string is empty
}
You can iterate through every character in the string and check if it is the space (" ") or newline ("\n") character. If not, return false. Else if you search through the whole string and didn't return false, it is "empty".
Something like this:
NSString* myStr = #"A STRING";
for(int i = 0; i < [myStr length]; i++)
{
if(!(([myStr characterAtIndex:i] == #' ') || ([myStr characterAtIndex:i] == #'\n')))
{
return false;
}
}

Resources