Форматиране на низ, съдържащ число със запетая

Имам число, съхранено в екземпляр NSMutableString, което искам да форматирам автоматично с разделители със запетаи и след това да покажа резултата в UITextField.

Опитах да използвам NSNumberFormatter за форматиране като валута, но не искам да показва десетични знаци, ако оригиналът NSMutableString не съдържа десетичен знак.

Например:

  • Ако NSMutableString съдържа "1234567", трябва да се форматира като "1,234,567".
  • Ако NSMutableString съдържа "1234567.1", то трябва да се форматира като "1,234,567.1"
  • Ако NSMutableString съдържа "1234567.12", то трябва да се форматира като "1,234,567.12"

Максималният десетичен знак, който NSMutableString ще съдържа, е 2.

Всяка помощ е много ценена.

Благодаря!


person staticnz    schedule 24.03.2012    source източник


Отговори (4)


Имайте предвид, че наистина трябва да локализирате това, ако взаимодействате с потребителите по този въпрос, но ето един начин да го направите:

- (NSString *)formatString:(NSString *)string {
    // Strip out the commas that may already be here:
    NSString *newString = [string stringByReplacingOccurrencesOfString:@"," withString:@""];
    if ([newString length] == 0) {
        return nil;
    }

    // Check for illegal characters
    NSCharacterSet *disallowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet];
    NSRange charRange = [newString rangeOfCharacterFromSet:disallowedCharacters];
    if ( charRange.location != NSNotFound) {
        return nil;
    }

    // Split the string into the integer and decimal portions
    NSArray *numberArray = [newString componentsSeparatedByString:@"."];
    if ([numberArray count] > 2) {
        // There is more than one decimal point
        return nil;
    }

    // Get the integer
    NSString *integer           = [numberArray objectAtIndex:0];
    NSUInteger integerDigits    = [integer length];
    if (integerDigits == 0) {
        return nil;
    }

    // Format the integer.
    // You can do this by first converting to a number and then back to a string,
    // but I would rather keep it as a string instead of doing the double conversion.
    // If performance is critical, I would convert this to a C string to do the formatting.
    NSMutableString *formattedString = [[NSMutableString alloc] init];
    if (integerDigits < 4) {
        [formattedString appendString:integer];
    } else {
        // integer is 4 or more digits
        NSUInteger startingDigits = integerDigits % 3;
        if (startingDigits == 0) {
            startingDigits = 3;
        }
        [formattedString setString:[integer substringToIndex:startingDigits]];
        for (NSUInteger index = startingDigits; index < integerDigits; index = index + 3) {
            [formattedString appendFormat:@",%@", [integer substringWithRange:NSMakeRange(index, 3)]];
        }
    }

    // Add the decimal portion if there
    if ([numberArray count] == 2) {
        [formattedString appendString:@"."];
        NSString *decimal = [numberArray objectAtIndex:1];
        if ([decimal length] > 0) {
            [formattedString appendString:decimal];
        }
    }

    return formattedString;
}

// Test cases:
NSLog(@"%@", [self formatString:@"123456"]);
NSLog(@"%@", [self formatString:@"1234567."]);
NSLog(@"%@", [self formatString:@"12345678.1"]);
NSLog(@"%@", [self formatString:@"123456789.12"]);

// Output:
123,456
1,234,567.
12,345,678.1
123,456,789.12
person lnafziger    schedule 25.03.2012
comment
Уау благодаря! Това работи перфектно. Съгласен съм с повторната локализация, но тъй като това приложение е за конкретна държава, избрах твърдо кодиран формат. - person staticnz; 25.03.2012

Просто извикайте този метод, за да бъде прост:

public static String GetCommaSeparatedCount(this Int32 Count)
    {
        // Check for The less-than character (<) is converted to &lt;
        String result = String.Format("{0:#,##0}", Count);

        return result;
    }
person Dinesh    schedule 16.10.2012

Търсите метода -setMinimumFractionDigits: на NSNumberFormatter. Задайте това на 0 и ще показва десетичната точка само ако има какво да се постави след нея.

person Amy Worrall    schedule 25.03.2012
comment
Благодаря, пробвах това и почти работи. Има няколко проблема, които ме объркват. Когато низът съдържа 1234., той ще покаже само 1234, така че потребителят няма да разбере, че натискането на десетичния клавиш е обработено. По някаква причина, ако низът е дълъг 9 знака, форматиращият променя числото, когато се форматира. Например, ако въведа 123456789, той се форматира като '123,456,792' - някаква идея защо се случва това? Ако е по-малко от 9 знака, влиза без проблем. - person staticnz; 25.03.2012
comment
Това е моят код: // Create formatter NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; [formatter setMinimumFractionDigits:0]; [formatter setGroupingSeparator:@","]; entryFieldFloat = [entryField doubleValue]; NSNumber * entryFieldNumber = [NSNumber numberWithDouble:entryFieldFloat]; [enterPrice setText:[NSString stringWithFormat:@"%@", [formatter stringFromNumber:entryFieldNumber]]]; - person staticnz; 25.03.2012

Мисля, че това трябва да го направи - добавих оператор if, за да проверя дали има десетична точка във въведената стойност. „Изход“ в този пример е свойство, което съм обвързал със стойността на текстово поле, за да покажа резултата.

-(IBAction)doConversion:(id)sender{
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
    [formatter setMaximumFractionDigits:2];
    [formatter setUsesGroupingSeparator:YES];
    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];

    double entryFieldFloat = [entryField doubleValue]; 
    if ([entryField.stringValue rangeOfString:@"."].length == 1) {
        formatter.alwaysShowsDecimalSeparator = YES;
        self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
    }else{
        formatter.alwaysShowsDecimalSeparator = NO;
        self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
    }
}
person rdelmar    schedule 25.03.2012