38

有没有办法使用 NSNumberFormatter 来获取 'th' 'st' 'nd' 'rd' 数字结尾?

编辑:

看起来它不存在。这是我正在使用的。

+(NSString*)ordinalNumberFormat:(NSInteger)num{
    NSString *ending;

    int ones = num % 10;
    int tens = floor(num / 10);
    tens = tens % 10;
    if(tens == 1){
        ending = @"th";
    }else {
        switch (ones) {
            case 1:
                ending = @"st";
                break;
            case 2:
                ending = @"nd";
                break;
            case 3:
                ending = @"rd";
                break;
            default:
                ending = @"th";
                break;
        }
    }
    return [NSString stringWithFormat:@"%d%@", num, ending];
}

改编自 nickf 在此处的回答 .NET 中是否有一种简单的方法可以获得数字的“st”、“nd”、“rd”和“th”结尾?

4

20 回答 20

43

从 iOS 9 开始,正确的方法是:

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterOrdinalStyle;

NSLog(@"%@", [numberFormatter stringFromNumber:@(1)]); // 1st
NSLog(@"%@", [numberFormatter stringFromNumber:@(2)]); // 2nd
NSLog(@"%@", [numberFormatter stringFromNumber:@(3)]); // 3rd, etc.

或者:

NSLog(@"%@", [NSString localizedStringFromNumber:@(1)
                                     numberStyle:NSNumberFormatterOrdinalStyle]); // 1st
于 2016-05-08T23:54:38.370 回答
22

这是一种方法(对于英语)。感谢 nickf https://stackoverflow.com/a/69284/1208690提供 PHP 中的原始代码,我只是将其改编为objective C:-

-(NSString *) addSuffixToNumber:(int) number
{
    NSString *suffix;
    int ones = number % 10;
    int tens = (number/10) % 10;

    if (tens ==1) {
        suffix = @"th";
    } else if (ones ==1){
        suffix = @"st";
    } else if (ones ==2){
        suffix = @"nd";
    } else if (ones ==3){
        suffix = @"rd";
    } else {
        suffix = @"th";
    }

    NSString * completeAsString = [NSString stringWithFormat:@"%d%@", number, suffix];
    return completeAsString;
}
于 2012-04-20T17:41:45.467 回答
21

从 iOS 9 开始

斯威夫特 4

private var ordinalFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.numberStyle = .ordinal
    return formatter
}()

extension Int {
    var ordinal: String? {
        return ordinalFormatter.string(from: NSNumber(value: self))
    }
}

最好将格式化程序放在扩展名之外......

于 2017-02-23T17:00:21.650 回答
18

其他 Swift 解决方案不会产生正确的结果并且包含错​​误。我已将 CmKndy 解决方案翻译成 Swift

extension Int {

    var ordinal: String {
        var suffix: String
        let ones: Int = self % 10
        let tens: Int = (self/10) % 10
        if tens == 1 {
            suffix = "th"
        } else if ones == 1 {
            suffix = "st"
        } else if ones == 2 {
            suffix = "nd"
        } else if ones == 3 {
            suffix = "rd"
        } else {
            suffix = "th"
        }
        return "\(self)\(suffix)"
    }

}

测试结果: 0日 1日 2日 3日 4日 5日 6日 7日 8日 9日 10日 11日 12日 13日 14日 15日 16日 17日 18日 19日 20日 21日 22日 23日

于 2015-01-19T13:44:36.137 回答
14

由于问题要求使用数字格式化程序,因此这是我制作的一个粗略的。

//
//  OrdinalNumberFormatter.h
//

#import <Foundation/Foundation.h>


@interface OrdinalNumberFormatter : NSNumberFormatter {

}

@end

和实施:

//
//  OrdinalNumberFormatter.m
//

#import "OrdinalNumberFormatter.h"


@implementation OrdinalNumberFormatter

- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
    NSInteger integerNumber;
    NSScanner *scanner;
    BOOL isSuccessful = NO;
    NSCharacterSet *letters = [NSCharacterSet letterCharacterSet];

    scanner = [NSScanner scannerWithString:string];
    [scanner setCaseSensitive:NO];
    [scanner setCharactersToBeSkipped:letters];

    if ([scanner scanInteger:&integerNumber]){
        isSuccessful = YES;
        if (anObject) {
            *anObject = [NSNumber numberWithInteger:integerNumber];
        }
    } else {
        if (error) {
            *error = [NSString stringWithFormat:@"Unable to create number from %@", string];
        }
    }

    return isSuccessful;
}

- (NSString *)stringForObjectValue:(id)anObject {
    if (![anObject isKindOfClass:[NSNumber class]]) {
        return nil;
    }

    NSString *strRep = [anObject stringValue];
    NSString *lastDigit = [strRep substringFromIndex:([strRep length]-1)];

    NSString *ordinal;


    if ([strRep isEqualToString:@"11"] || [strRep isEqualToString:@"12"] || [strRep isEqualToString:@"13"]) {
        ordinal = @"th";
    } else if ([lastDigit isEqualToString:@"1"]) {
        ordinal = @"st";
    } else if ([lastDigit isEqualToString:@"2"]) {
        ordinal = @"nd";
    } else if ([lastDigit isEqualToString:@"3"]) {
        ordinal = @"rd";
    } else {
        ordinal = @"th";
    }

    return [NSString stringWithFormat:@"%@%@", strRep, ordinal];
}

@end

将其实例化为 Interface Builder 对象并将文本字段的格式化程序出口附加到它。为了更好地控制(例如设置最大值和最小值,您应该创建格式化程序的实例,根据需要设置属性并使用它的setFormatter:方法将其附加到文本字段。

您可以从 GitHub 下载该类(包括示例项目)

于 2010-07-23T07:09:47.900 回答
14

-- 斯威夫特 4/5 --

     let num = 1
     let formatter = NumberFormatter()
     formatter.numberStyle = .ordinal
     let day = formatter.string(from: NSNumber(value: num))
     
     print(day!)
     result - 1st
于 2017-12-29T10:11:57.517 回答
7

英文很简单。这是一个快速的扩展:

extension Int {
    var ordinal: String {
        get {
            var suffix = "th"
            switch self % 10 {
                case 1:
                    suffix = "st"
                case 2:
                    suffix = "nd"
                case 3:
                    suffix = "rd"
                default: ()
            }
            if 10 < (self % 100) && (self % 100) < 20 {
                suffix = "th"
            }
            return String(self) + suffix
        }
    }
}

然后调用类似的东西:

    cell.label_position.text = (path.row + 1).ordinal
于 2014-11-14T06:17:20.733 回答
5

只需添加另一个实现作为类方法。直到我从 php.ini 中的示例实现此问题后,我才看到发布此问题。

+ (NSString *)buildRankString:(NSNumber *)rank
{
    NSString *suffix = nil;
    int rankInt = [rank intValue];
    int ones = rankInt % 10;
    int tens = floor(rankInt / 10);
    tens = tens % 10;
    if (tens == 1) {
        suffix = @"th";
    } else {
        switch (ones) {
            case 1 : suffix = @"st"; break;
            case 2 : suffix = @"nd"; break;
            case 3 : suffix = @"rd"; break;
            default : suffix = @"th";
        }
    }
    NSString *rankString = [NSString stringWithFormat:@"%@%@", rank, suffix];
    return rankString;
}
于 2012-06-07T00:39:19.150 回答
5

这是一个适用于所有整数类型的紧凑 Swift 扩展:

extension IntegerType {
    func ordinalString() -> String {
        switch self % 10 {
        case 1...3 where 11...13 ~= self % 100: return "\(self)" + "th"
        case 1:    return "\(self)" + "st"
        case 2:    return "\(self)" + "nd"
        case 3:    return "\(self)" + "rd"
        default:   return "\(self)" + "th"
        }
    }
}

示例用法:

let numbers = (0...30).map { $0.ordinalString() }
print(numbers.joinWithSeparator(", "))

输出:

0日、1日、2日、3日、4日、5日、6日、7日、8日、9日、10日、11日、12日、13日、14日、15日、16日、17日、18日、19日、20日、21日、22日、23日、24日、 25 日、26 日、27 日、28 日、29 日、30 日

于 2016-03-15T19:46:16.930 回答
5

有一个简单的解决方案

迅速

let formatter = NumberFormatter()
formatter.numberStyle = .ordinal
let first = formatter.string(from: 1) // 1st
let second = formatter.string(from: 2) // 2nd

对象-c

NSNumberFormatter *numberFormatter = [NSNumberFormatter new];
numberFormatter.numberStyle = NSNumberFormatterOrdinalStyle;
NSString* first = [numberFormatter stringFromNumber:@(1)]; // 1st
NSString* second = [numberFormatter stringFromNumber:@(2)]; // 2nd

参考:hackingwithswift.com

于 2017-08-28T09:20:27.300 回答
3

我不知道这种能力。但是,您可以自己执行此操作。在英语中,序数(th、st、nd、rd 等)有一个非常简单的模式:

如果数字以:=> 结尾,请使用:

  • 0 => 日
  • 1 => st
  • 2 => 发现
  • 3 => rd
  • 4 => 日
  • 5 => 日
  • 6 => 日
  • 7 => 日
  • 8 => 日
  • 9 => 日
  • 11 => 日
  • 12 => 日
  • 13 => 日

这不会为您拼出单词,但它可以让您执行以下操作:“42nd”、“1,340,697th”等。

如果您需要本地化,这会变得更加复杂。

于 2010-07-22T20:11:21.737 回答
3

干净的 Swift 版本(仅适用于英语):

func ordinal(number: Int) -> String {
    if (11...13).contains(number % 100) {
        return "\(number)th"
    }
    switch number % 10 {
        case 1: return "\(number)st"
        case 2: return "\(number)nd"
        case 3: return "\(number)rd"
        default: return "\(number)th"
    }
}

可以作为扩展来完成Int

extension Int {

    func ordinal() -> String {
        return "\(self)\(ordinalSuffix())"
    }

    func ordinalSuffix() -> String {
        if (11...13).contains(self % 100) {
            return "th"
        }
        switch self % 10 {
            case 1: return "st"
            case 2: return "nd"
            case 3: return "rd"
            default: return "th"
        }
    }

}
于 2016-02-21T20:41:51.163 回答
2

下面的示例演示如何处理任何数字。它在 c# 中,但可以轻松转换为任何语言。

http://www.bytechaser.com/en/functions/b6yhfyxh78/convert-number-to-ordinal-like-1st-2nd-in-c-sharp.aspx

于 2010-07-22T20:41:43.587 回答
2

这会将日期转换为字符串,并在日期中添加序数。您可以通过更改NSDateFormatter对象来修改日期格式

-(NSString*) getOrdinalDateString:(NSDate*)date
{
    NSString* string=@"";
    NSDateComponents *components = [[NSCalendar currentCalendar] components: NSCalendarUnitDay fromDate:date];

    if(components.day == 1 || components.day == 21 || components.day == 31)
        string = @"st";

    else if (components.day == 2 || components.day == 22)
        string = @"nd";

    else if (components.day == 3 || components.day == 23)
        string = @"rd";

    else
        string = @"th";


    NSDateFormatter *dateFormatte = [[NSDateFormatter alloc] init];
    [dateFormatte setFormatterBehavior:NSDateFormatterBehavior10_4];
    [dateFormatte setDateFormat:[NSString stringWithFormat:@"d'%@' MMMM yyyy",string]];

    NSString *dateString = [dateFormatte stringFromDate:date];
    return dateString;
}
于 2015-12-28T12:09:34.957 回答
1

这是一个 Swift 解决方案,它循环遍历用户的首选语言,直到找到具有已知规则(很容易添加)的序数:

    extension Int {
        var localizedOrdinal: String {

            func ordinalSuffix(int: Int) -> String {
                for language in NSLocale.preferredLanguages() as [String] {

                switch language {
                    case let l where l.hasPrefix("it"):
                        return "°"
                    case let l where l.hasPrefix("en"):
                        switch int {
                        case let x where x != 11 && x % 10 == 1:
                            return "st"
                        case let x where x != 12 && x % 10 == 2:
                            return "nd"
                        case let x where x != 13 && x % 10 == 3:
                            return "rd"
                        default:
                            return "th"
                        }
                    default:
                        break
                    }
                }

                return ""
            }

            return "\(self)" + ordinalSuffix(self)
        }
    }
于 2014-11-18T14:17:11.363 回答
0

这里的许多解决方案都不能处理像 112 这样的更高数字。这是一种简单的方法。

for(int i=0;i<1000;i++){
    int n = i;
    NSString* ordinal = @"th";
    if(n%10==1 && n%100!=11) ordinal = @"st";
    if(n%10==2 && n%100!=12) ordinal = @"nd";
    if(n%10==3 && n%100!=13) ordinal = @"rd";
    NSLog(@"You are the %d%@",i,ordinal);
}
于 2015-08-19T21:24:18.433 回答
0

这是英语的简短 Int 扩展,它也正确解释和显示负整数:

extension Int {
    func ordinal() -> String {
        let suffix: String!
        // treat negative numbers as positive for suffix
        let number = (self < 0 ? self * -1 : self)

        switch number % 10 {
        case 0:
            suffix = self != 0 ? "th" : ""
        case 1:
            suffix = "st"
        case 2:
            suffix = "nd"
        case 3:
            suffix = "rd"
        default:
            suffix = "th"
        }

        return String(self) + suffix
    }
}
于 2016-09-13T19:12:39.113 回答
0
- (NSString *) formatOrdinalNumber:(NSInteger )number{
    NSString *result = nil;
    //0 remains just 0
    if (number == 0) {
        result = @"0";
    }

    //test for number between 3 and 21 as they follow a
    //slightly different rule and all end with th
    else if (number > 3 && number < 21)
    {
        result = [NSString stringWithFormat:@"%ld th",(long)number];
    }
    else {
        //return the last digit of the number e.g. 102 is 2
        NSInteger lastdigit = number % 10;
        switch (lastdigit)
        {
            case 1: result = [NSString stringWithFormat:@"%ld st",(long)number]; break;
            case 2: result = [NSString stringWithFormat:@"%ld nd",(long)number]; break;
            case 3: result = [NSString stringWithFormat:@"%ld rd",(long)number]; break;
            default: result = [NSString stringWithFormat:@"%ld th",(long)number];
        }
    }
    return result;
}
于 2017-05-05T07:04:21.307 回答
0

你可以试试这个,它很好地简化了。

function numberToOrdinal(n) {

  if (n==0) {
    return n;
   }
   var j = n % 10,
       k = n % 100;


   if (j == 1 && k != 11) {
       return n + "st";
   }
   if (j == 2 && k != 12) {
       return n + "nd";
   }
   if (j == 3 && k != 13) {
       return n + "rd";
   }
   return n + "th";
}
于 2019-04-19T12:44:26.887 回答
-4

这是我采用 NSString* 表示日期并返回序数值的蛮力实现。我觉得它更容易阅读。

NSDictionary *ordinalDates = @{
    @"1": @"1st",
    @"2": @"2nd",
    @"3": @"3rd",
    @"4": @"4th",
    @"5": @"5th",
    @"6": @"6th",
    @"7": @"7th",
    @"8": @"8th",
    @"9": @"9th",
    @"10": @"10th",
    @"11": @"11th",
    @"12": @"12th",
    @"13": @"13th",
    @"14": @"14th",
    @"15": @"15th",
    @"16": @"16th",
    @"17": @"17th",
    @"18": @"18th",
    @"19": @"19th",
    @"20": @"20th",
    @"21": @"21st",
    @"22": @"22nd",
    @"23": @"23rd",
    @"24": @"24th",
    @"25": @"25th",
    @"26": @"26th",
    @"27": @"27th",
    @"28": @"28th",
    @"29": @"29th",
    @"30": @"30th",
    @"31": @"31st" };
于 2014-02-03T15:51:29.697 回答