Convert a string to a positive or negative number - objective-c

I am new to ObjC. I've spent years working in Applescript and I've decided to move up. I am a hobbiest programmer.
I have the following code:
+(NSArray *) initArrayWithFileContents:(NSString *) theFilePath
{
NSString *theContents = [(self) loadFile:theFilePath]; // returns the contents of a text file
NSArray *theParagraphs = [(self) getParagraphs:theContents]; // returns the contents as an array of paragraphs
NSMutableArray *teamData = [[NSMutableArray alloc] init]; // array of team data
NSMutableArray *leagueData = [[NSMutableArray alloc] init]; // array of arrays
NSNumberFormatter *numberStyle = [[NSNumberFormatter alloc] init];
[numberStyle setNumberStyle:NSNumberFormatterDecimalStyle];
for (NSString *currentParagraph in theParagraphs)
{
NSArray *currentTeam = [(self) getcolumnarData:currentParagraph];
for (NSString *currentItem in currentTeam)
{
NSNumber *currentStat = [numberStyle numberFromString:currentItem];
if (currentStat != Nil) {
[teamData addObject:currentStat];
} else {
[teamData addObject:currentItem];
}
}
[leagueData addObject:teamData];
[teamData removeAllObjects];
}
return leagueData;
}
This works fine for strings and for negative numbers, but a number preceded by a "+" sign is returned as a string. I figure I need to use a different number formatter style but I don't know what to use.
Thanks in advance,
Brad

NSNumberFormatter *numberStyle = [[NSNumberFormatter alloc] init];
[numberStyle setNumberStyle:NSNumberFormatterDecimalStyle];
[numberStyle setPositiveFormat:#"'+'#"] ;
or
NSNumberFormatter *numberStyle = [[NSNumberFormatter alloc] init];
[numberStyle setNumberStyle:NSNumberFormatterDecimalStyle];
[numberStyle setPositivePrefix:#"+"] ;

You could remove the + sign if one exists:
if ([currentItem hasPrefix:#"+"])
{
currentItem = [currentItem substringWithRange:NSMakeRange(1, [currentItem length] -1)];
}
Probably a better way, but this would work.

What ended up working for me was to create 2 NSNumberFormatters; 1 for decimals and 1 for decimals using the setPositiveFormat: method as described above. If the first formatter doesn't work, it'll flow on to the next formatter using the positive format.

Related

Algorithm to convert 1 to "One" and so on in objective-c [duplicate]

This question already has answers here:
How to convert numbers into text?
(8 answers)
Closed 7 years ago.
I'm looking for an algorithm or function to convert integer number 0,1,2 to Zero,One,Two respectively. How can we do this in Objective-C ?
Apple has a lot of handy formatting functionality built in for many data types. Called a "formatter," they can convert objects to/from string representations.
For your case, you will be using NSNumberFormatter, but if you have an integer you need to convert it to an NSNumber first. See below example.
NSInteger anInt = 11242043;
NSString *wordNumber;
//convert to words
NSNumber *numberValue = [NSNumber numberWithInt:anInt]; //needs to be NSNumber!
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterSpellOutStyle];
wordNumber = [numberFormatter stringFromNumber:numberValue];
NSLog(#"Answer: %#", wordNumber);
// Answer: eleven million two hundred forty-two thousand forty-three
This is my code for 0 to 100 (You can update as per your requirement). WORKING PERFECTLY !!
-(NSDictionary *)algorithm
{
NSArray *myArray = #[#"Zero",#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine",#"Ten",#"Eleven",#"Twelve",#"Thirteen",#"Fourteen",#"Fifteen",#"Sixteen",#"Sevteen",#"Eighteen",#"Nineteen"];
NSArray *tensArray = #[#"Twenty",#"Thirty",#"Fourty",#"Fifty",#"Sixty"
,#"Seventy",#"Eighty",#"Ninety",#"One Hundred"];
NSMutableDictionary *numberStringDictionary = [[NSMutableDictionary alloc] init];
NSMutableArray *numberStringsArray = [[NSMutableArray alloc] init];
for(int i=0;i<=100;i++)
{
if(i<20)
{
[numberStringDictionary setObject:myArray[i] forKey:[NSString stringWithFormat:#"%d",i]];
[numberStringsArray addObject:myArray[i]];
NSLog(#"\n%#",myArray[i]);
}
else if(i%10==0)
{
[numberStringDictionary setObject:tensArray[i/10-2] forKey:[NSString stringWithFormat:#"%d",i]];
[numberStringsArray addObject:tensArray[i/10-2]];
NSLog(#"\n%#",tensArray[i/10-2]);
}
else
{
[numberStringDictionary setObject:[NSString stringWithFormat:#"%# %#",tensArray[i/10-2],myArray[i%10]] forKey:[NSString stringWithFormat:#"%d",i]];
[numberStringsArray addObject:[NSString stringWithFormat:#"%# %#",tensArray[i/10-2],myArray[i%10]]];
NSLog(#"%#",[NSString stringWithFormat:#"%# %#",tensArray[i/10-2],myArray[i%10]]);
}
}
return numberStringDictionary;
}

Using NSNumber to sort numerous integers

Ive been doing alot of research and can't quite grasp resolving this issue. In my application I have several text fields that save integer values in the form of int variables (at least 15 int variables). My main goal is to sort out high to low numbers that were saved from the text fields.
Now would I use the following code to convert each seperate integer variable into a new NSNumber, than use a sort function to sort out the new NSNumbers from high to low?
NSNumber *newNumber = [NSNumber numberWithInt: my_int_variable];
I just feel as if this is a redundant way of sorting 12 integer variables and there is a easier way. Thank you for the help
Going from individual text fields to strings to ints to NSNumbers to an array to a sorted array is long, clunky trip. But a worthwhile trip nevertheless.
// assume these
UITextField *field0;
UITextField *field1;
UITextField *field2;
// make an array for the input and the result
NSArray *textFields = #[field0, field1, field2];
NSMutableArray *numbers = [#[] mutableCopy];
// prepare a number formatter
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
// lots of choices here. see https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/index.html
for (UITextField *textField in textFields) {
NSString *text = textField.text;
NSNumber *number = [formatter numberFromString:text];
[numbers addObject:number];
}
// sort...a few choices here, too. taking the simplest:
[numbers sortUsingSelector:#selector(compare:)];
NSLog(#"ta da: %#", numbers);
Or did you want to sort the text fields based on their contents? Doable too:
NSMutableArray *textFields = [#[field0, field1, field2] mutableCopy];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
[textFields sortedUsingComparator: ^(id objA, id objB) {
NSString *textA = ((UITextField *)objA).text;
NSString *textB = ((UITextField *)objB).text;
NSNumber *numberA = [formatter numberFromString:textA];
NSNumber *numberB = [formatter numberFromString:textB];
return [numberA compare:numberB];
}];
NSLog(#"text fields in order of their contents: %#", textFields);

NSNumberFormatter: dispatch_once where Currency changes

I have a tableview where a list of NSDecimalNumber will be displayed with their own currencies.
I use a dispatch_once on a NSNumberFormatter but notice that sometimes it'll totally ignore my commands to set the fraction digits or suffix on fraction digits altogether.
Currently the only way I've been able to resolve this is to init the NSNumberFormatter every row which is a bit silly.
ie:
- (NSNumberFormatter *)currencyFormatWithCurrency:(NSString *)currency
{
static NSNumberFormatter *_formatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_formatter = [[NSNumberFormatter alloc] init];
});
[_formatter setCurrencyCode:currency];
[_formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[_formatter setMaximumFractionDigits:0];
[_formatter setGeneratesDecimalNumbers:NO];
[_formatter setRoundingMode:NSNumberFormatterRoundUp];
return _formatter;
}
// someCurrency is a string that will change per row
// someAmount is a NSDecimalNumber that will change per row
NSNumberFormatter *formatter = [self currencyFormatWithCurrency:someCurrency];
NSString *formattedAmount = [formatter stringFromNumber:someAmount];
self.amountLabel.text = formattedAmount;
Sometimes with the above if I feed in a figure like 80000, it'll return 80,000.00 (sometimes it depends on the currency).
I guess I could just init the NSNumberFormatter and nil it on each row.
Perhaps I'm doing it wrong, but if there is perhaps a way to ensure that I don't need to keep creating the NSNumberFormatter to ensure it'll understand the rules I give it?
Many thanks
NSNumberFormatter is not thread safe. That will lead to all kinds of problems. (Well, the way you use it cannot really be thread safe, because you might be modifying it in one thread while another thread is using it, but just using an NSNumberFormatter from two threads is not safe).
You can always do something in a method like
NSString* lastCurrency = nil;
NSNumberFormatter* formatter = nil;
for (;;) {
...
NSString* currency = ...;
if (! [lastCurrency isEqualToString:currency]) {
lastCurrency = currency;
formatter = ...;
}
}
Works well if in most cases the currency is unchanged.
I think this is a possible solution which I got from the following website might help things.
NSString *HTCurrencyString(double amount, NSString *currencyCode)
{
static NSString *currencyFormatterKey = #"HTCurrencyFormatter";
NSNumberFormatter *currencyFormatter = [[NSThread currentThread] threadDictionary][currencyFormatterKey];
if (currencyFormatter == nil)
{
currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormatter setLocale:[NSLocale currentLocale]];
[[NSThread currentThread] threadDictionary][currencyFormatterKey] = currencyFormatter;
}
[currencyFormatter setCurrencyCode:currencyCode];
[currencyFormatter setMaximumFractionDigits:0];
[currencyFormatter setRoundingMode:NSNumberFormatterRoundHalfUp];
return [currencyFormatter stringFromNumber:#(amount)];
}

Class method returning empty array

I have written a class method that converts columnar data from a text file and returns an array of arrays...only it is returning an EMPTY array of EMPTY arrays.
+(NSArray *) initArrayWithFileContents:(NSString *) theFilePath
{
NSString *theContents = [self loadFile:theFilePath];
NSArray *theParagraphs = [self getParagraphs:theContents];
NSMutableArray *teamData = [[NSMutableArray alloc] init]; // array of team data
NSMutableArray *leagueData = [[NSMutableArray alloc] init]; // array of arrays
// set up number formatters for getting numbers from strings
NSNumberFormatter *numberStyle = [[NSNumberFormatter alloc] init];
NSNumberFormatter *positiveNumberStyle = [[NSNumberFormatter alloc] init];
[numberStyle setNumberStyle:NSNumberFormatterDecimalStyle];
[positiveNumberStyle setNumberStyle:NSNumberFormatterDecimalStyle];
[positiveNumberStyle setPositiveFormat:#"'+'#"];
// set up a date and time formatter for getting time data from strings
NSDateFormatter *timeStyle = [[NSDateFormatter alloc] init];
[timeStyle setDateStyle:NSDateFormatterNoStyle];
[timeStyle setDateFormat:#" mm:ss"];
for (NSString *currentParagraph in theParagraphs)
{
NSArray *currentTeam = [self getcolumnarData:currentParagraph]; // get an array of strings
for (NSString *currentItem in currentTeam)
{
NSNumber *currentStat = [numberStyle numberFromString:currentItem];
if (currentStat != Nil) {
[teamData addObject:currentStat]; // number found
} else {
currentStat = [positiveNumberStyle numberFromString:currentItem];
if (currentStat != Nil) {
[teamData addObject:currentStat]; // number with '+' sign found
} else {
NSDate *currentTime = [timeStyle dateFromString:currentItem];
if (currentTime != Nil) {
NSNumber *theSeconds = [self calculateSeconds: currentTime];
[teamData addObject:theSeconds]; // time found
} else {
[teamData addObject:currentItem]; // string found
}
}
}
}
[leagueData addObject:teamData]; // add child array to end of parent array
[teamData removeAllObjects]; // reset child array
}
NSArray *dataToReturn = [NSArray arrayWithArray:leagueData]; // convert to NSArray to return
return dataToReturn;
}
In my debugging efforts I have verified that either an NSString or NSNumber is being added to the end of the teamData array but when adding teamData to leagueData an empty object is added. What am I missing?
Thanks in advance,
Brad
Move
NSMutableArray *teamData = [[NSMutableArray alloc] init];
into the loop:
for (NSString *currentParagraph in theParagraphs)
{
NSMutableArray *teamData = [[NSMutableArray alloc] init];
// ...
[leagueData addObject:teamData];
}
loop. At present, you always add the same array to leagueData.
An array "only" keeps pointers to its elements, so at the end all elements
of leagueData point to the same array teamData (from which you have removed
all objects).

How can i display the number in such a format?

I am displaying a number in textfield. Which displays the number as "1234" but i want to display it as in format of "1,234" if i enter another large number which displays as "12345" but i want to display it as "12,345" if i enter 123456 which has to display as "123,456" . How do I format this number in desired format?
-(void)clickDigit:(id)sender
{
NSString * str = (NSString *)[sender currentTitle];
NSLog(#"%#",currentVal);
if([str isEqualToString:#"."]&& !([currentVal rangeOfString:#"."].location == NSNotFound) )
{
return;
}
if ([display.text isEqualToString:#"0"])
{
currentVal = str;
[display setText:currentVal];
}
else if([currentVal isEqualToString:#"0"])
{
currentVal=str;
[display setText:currentVal];
}
else
{
if ([display.text length] <= MAXLENGTH)
{
currentVal = [currentVal stringByAppendingString:str];
NSLog(#"%#",currentVal);
[display setText:currentVal];
}
currentVal=display.text;
}
}
This is the code i am using to display the number in textfield.
EDIT: I Changed my code into the following but still don't get the number correctly formatted:
if ([display.text length] <= MAXLENGTH) {
currentVal = [currentVal stringByAppendingString:str];
NSNumberFormatter * myNumFormatter = [[NSNumberFormatter alloc] init];
[myNumFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *tempNum = [myNumFormatter numberFromString:currentVal];
NSLog(#"My number is %#",tempNum);
[display setText:[tempNum stringValue]];
currentVal=display.text;
}
You can do it like this:
int myInt = 12345;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *number = [NSNumber numberWithInt:myInt];
NSLog(#"%#", [formatter stringFromNumber:number]); // 12,345
Edit
You didn't implement this correctly, the key is to obtain the string representation of the number using [formatter stringFromNumber:number], but you didn't do that. So change your code into:
currentVal = [currentVal stringByAppendingString:str];
NSNumberFormatter * myNumFormatter = [[NSNumberFormatter alloc] init];
[myNumFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *tempNum = [myNumFormatter numberFromString:currentVal];
NSLog(#"My number is %#",tempNum);
[display setText:[myNumFormatter stringFromNumber:tempNum]]; // Change this line
currentVal=display.text;
NSLog(#"My formatted number is %#", currentVal);
First, read through the list of methods on the NSNumberFormatter reference page. After doing that, you'll probably realize that you need to use the -setHasThousandSeparators: method to turn on the thousand separators feature. You can also use the -setThousandSeparator: method to set a custom separator, though you probably won't need to do that.