将以标志枚举表示的天数转换为易于理解的日期

3
// Values of the individual days as powers of two
enum {
    kMonday = 64,
    kTuesday = 32,
    kWednesday = 16,
    kThursday = 8,
    kFriday = 4,
    kSaturday = 2,
    kSunday = 1,
};

如何最快地将所有127种天数变化转换为易读的字符串?

例如,如果我得到数字7,我希望输出“星期五-星期日”。

如果我得到数字66,我希望输出“星期一,星期六”。

2个回答

3

基本上你有两个选择:

  • 创建一个工厂,将合并的天数整数传递给它,然后获取字符串

  • 创建包装对象,包装整数并提供访问内部逻辑的方法

我写了一个包装器:

#import <Foundation/Foundation.h>

typedef NS_OPTIONS(NSUInteger, WeekDays) {
    kMonday     = 1 << 6,
    kTuesday    = 1 << 5,
    kWednesday  = 1 << 4,
    kThursday   = 1 << 3,
    kFriday     = 1 << 2,
    kSaturday   = 1 << 1,
    kSunday     = 1 << 0
};

@interface DaysWrapper : NSObject
-(id)initWithDays:(WeekDays)weekDays;
@end

@interface DaysWrapper ()
@property (nonatomic,retain) NSMutableArray *days;
@end


@implementation DaysWrapper{
    int internalDays;
}

+(instancetype)dayWrapperWithDayBitmask:(WeekDays)daybits
{
    return [[DaysWrapper alloc] initWithDays:daybits];
}

-(instancetype)initWithDays:(WeekDays)weekDays
{
    if (self = [super init]) {
        WeekDays wholeWeek = 127;
        internalDays = weekDays & wholeWeek;
        _days = [@[] mutableCopy];

        while (wholeWeek) {
            wholeWeek >>= 1;
            if (weekDays & (wholeWeek +1)) {
                [_days addObject:[NSNumber numberWithBool:YES]];
            } else {
                [_days addObject:[NSNumber numberWithBool:NO]];
            }
        }
    }
    return self;
}

-(NSString *)description
{
    static dispatch_once_t onceToken;
    static NSArray *dayNames;
    static NSDictionary *fullnamesForDayNames;
    dispatch_once(&onceToken, ^{
        dayNames = @[@"Mon", @"Tues", @"Wend",@"Thu", @"Fri",@"Sat", @"Sun"];
        fullnamesForDayNames = [[NSDictionary alloc] initWithObjects: @[@"Monday",@"Tuesday",@"Wendsday",@"Thursday",@"Friday",@"Saturday",@"Sunday"]
                                                             forKeys:dayNames];
    });


    NSMutableString *returnSting = [@"" mutableCopy];
    __block BOOL previousWasAvailable = NO;
    NSMutableArray *dayRanges = [@[] mutableCopy];
    [self.days enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if (!previousWasAvailable && [obj boolValue])
            [dayRanges addObject:[@[] mutableCopy]];

        if ([obj boolValue]) {
            NSMutableArray *actualRange = [dayRanges lastObject];
            [actualRange addObject:dayNames[idx]];
        }
        previousWasAvailable = [obj boolValue];
    }];

    [dayRanges enumerateObjectsUsingBlock:^(NSMutableArray *rangeArray, NSUInteger idx, BOOL *stop) {

        if ([returnSting length]){
            [returnSting appendString:@","];
        }

        if ([rangeArray count] > 1) {
            [returnSting appendString: [rangeArray firstObject]];

            if ([rangeArray count] > 2){
                [returnSting appendString:@"-"];
            } else {
                [returnSting appendString:@","];
            }
        }

        if (idx == [dayRanges count]-1){
            [returnSting appendString: fullnamesForDayNames[[rangeArray lastObject]]];
        } else {
            [returnSting appendString:[rangeArray lastObject]];
        }
    }];

    return returnSting;
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {

        WeekDays monAndFriday    = kMonday | kFriday;
        WeekDays thurToSat       = kThursday | kFriday | kSaturday;
        WeekDays weekEnd         = kFriday | kSaturday | kSunday;
        WeekDays mondAndWeekend  = weekEnd | kMonday;
        WeekDays friSat          = kFriday | kSaturday;
        WeekDays everySecondDay  = 8 | 32 | 2;
        WeekDays moday           = kMonday;
        WeekDays workWeek        = kMonday | kTuesday | kWednesday | kThursday | kFriday;
        WeekDays wholeWeek       = workWeek | weekEnd;
        WeekDays notThursday     =  ~kThursday & wholeWeek;

        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:monAndFriday]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:weekEnd]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:thurToSat]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:mondAndWeekend]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:friSat]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:everySecondDay]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:moday]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:workWeek]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:wholeWeek]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:notThursday]);
    }
    return 0;
}

输出

Mon,Friday
Fri-Sunday
Thu-Saturday
Mon,Fri-Sunday
Fri,Saturday
Tues,Thu,Saturday
Monday
Mon-Friday
Mon-Sunday
Mon-Wend,Fri-Sunday

随机想法

  • 不要在数组名称self.days中保存整数信息的副本,每次需要时可以即时处理以减少空间占用。
  • 工厂基本上具有相同的逻辑。

代码总体检修(ARC、现代Obj-C语法、NS_OPTIONS等)- 2015年5月21日


请注意,通过将以下日期范围分组为数组,然后处理这些数组,我能够大大简化描述方法。 - vikingosegundo
请注意,我更改了代码以写出最后一天的名称,如您在帖子中显示。 - vikingosegundo

3
这是一个有趣的挑战。
#import <Foundation/Foundation.h>
enum {
    kMonday = 1 << 0,
    kTuesday = 1 << 1,
    kWednesday = 1 << 2,
    kThursday = 1 << 3,
    kFriday = 1 << 4,
    kSaturday = 1 << 5,
    kSunday = 1 << 6,
};
typedef int DayBits;

NSString * const shortDayNames[] = { @"Mon", @"Tues", @"Wed", @"Thurs", @"Fri", @"Sat", @"Sun" };
NSString * const fullDayNames[] = { @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", @"Sunday" };


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        // Demo all possible combinations
        for( DayBits days_as_bits = 0; days_as_bits < 128; days_as_bits++ ){
            // Create an index set from the bits
            NSMutableIndexSet * indexes = [NSMutableIndexSet indexSet];
            for( int bit = 0; bit < 7; bit++ ){
                if( days_as_bits & (1 << bit) ){
                    [indexes addIndex:bit];
                }
            }

            // Create string for result
            NSMutableString * daysDesc = [NSMutableString string];
            // Enumerate the index set backwards and build up the string
            __block BOOL contiguous = NO;
            [indexes enumerateIndexesWithOptions:NSEnumerationReverse 
                                      usingBlock:^(NSUInteger idx, BOOL *stop) {
                // Use short names unless this is the name that will appear 
                // at the end of the string
                NSString * const * dayNames = shortDayNames;
                if (0 == [daysDesc length]) {
                    dayNames = fullDayNames;
                }
                // If the previous index is present, we're working on a contiguous set
                if( [indexes containsIndex:(idx - 1)] ){
                    // If we were already in a contiguous set, just continue
                    if( contiguous ){
                        return;
                    }
                    // This is the end day of a contiguous set; place the name 
                    // and a hyphen
                    else {
                        [daysDesc insertString:[NSString stringWithFormat:@"-%@", dayNames[idx]]
                                                                  atIndex:0];
                        contiguous = YES;
                        return;
                    }
                }
                // We've reached the start day of a set. 
                // Turn off contiguous and fall through
                else {
                    contiguous = NO;
                }

                // Place a comma and today's name
                [daysDesc insertString:[NSString stringWithFormat:@", %@", dayNames[idx]]
                                                          atIndex:0];
            }];
            // Clean up extraneous comma and space at the beginning of the string
            daysDesc = [daysDesc stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" ,"]];
            NSLog(@"%d: %@", days_as_bits, daysDesc);
        }

    }
    return 0;
}

请注意,我调换了您的枚举以使其起作用,因此这可能对您完全无用,但希望有所帮助。这意味着例如7是kMonday | kTuesday | kWednesday而不是kFriday | kSaturday | kSunday,结果是星期一至星期三
我认为使用索引集可能是我能提供的主要见解。
您也许可以通过一些工作(撤消枚举的反向等)将事物切换回来;我已经浪费了足够的时间^W^W^W满足了我的好奇心。

也应该考虑到 NSIndexSet。 - vikingosegundo
如果索引集提供了更多的查询方式,那将是更好的。我开始使用它是因为我希望找到一种方法可以一次性地获取连续范围(就像“description”所存储/显示的方式),但最终这基本上与逐位迭代相同。 - jscs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接