2

I have an array of days (in string format) that my program receives from user input that is somewhere between 1-7 in length. The array that is received has the day name in full text.

An example of an array I might receive is: ["Tuesday", "Monday", "Thursday"]

What I'm trying to do is sort this array from Monday to Sunday and convert the full text names to abbreviations. So my sort function for the above array would ideally return: ["M", "Tu", "Th"].

Duplicates of same day will never appear, there will never be less than 1 item and never more than 7.

Thanks.

It's crude, but this is the rough UI the user is selecting days from:

enter image description here

I used the selected answer but adapted it to just add it into the one place I needed it. I adapted it as follows:

-(NSArray*)array:(NSArray*)array collect:(id(^)(id object))block
{
    NSMutableArray * result = [ NSMutableArray array ] ;
    for( id object in array ) { [ result addObject:block( object) ] ; }
    return result ;
}

-(NSArray*)arrayBySortingAndAbbreviatingDayNames:(NSArray*)arrayToSort
{
    NSArray * dayNames = @[ @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday",     @"Saturday", @"Sunday" ] ;
    NSArray * abbreviations = @[ @"M", @"Tu", @"W", @"Th", @"F", @"Sa", @"Su" ] ;
    NSArray * array = [ self array:arrayToSort collect:^(NSString * dayName){
        return @([ dayNames indexOfObject:dayName ]) ;
    } ] ;
    array = [ array sortedArrayUsingSelector:@selector( compare: ) ] ;
    array = [ self array:array collect:^(NSNumber * index){
        return abbreviations[ [ index integerValue ] ] ;
    }];
    return array ;
}
5
  • 1
    You would be much better off if your received data is in numbers instead of the text names. In other words, when the user chooses "Monday" (from their point of view), you save off 1 (0 is Sunday). Then your array becomes a list of numbers from 0 to 6. That makes it easy to sort and it makes it easy to look up the proper names. Commented May 14, 2013 at 1:21
  • looks like homework to me... but I posted anyway to be clever. better solutions? Commented May 14, 2013 at 1:23
  • It isn't homework. I'm building an application for drink specials that allows users to edit/add specials. This array is received when user selects the day a special is valid. Commented May 14, 2013 at 1:25
  • I think you should really store the user's selections as an array of day indexes... Then you don't have to jump through any hoops. Commented May 14, 2013 at 1:59
  • thought of a much better way... see my updated answer. Commented May 14, 2013 at 18:53

2 Answers 2

3
@implementation NSArray (DayNameThing)

-(NSArray*)collect:(id(^)(id object))block
{
    NSMutableArray * result = [ NSMutableArray array ] ;
    for( id object in self ) { [ result addObject:block( object) ] ; }
    return result ;
}

-(NSArray*)arrayBySortingAndAbbreviatingDayNames
{
    NSArray * dayNames = @[ @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", @"Sunday" ] ;
    NSArray * abbreviations = @[ @"M", @"Tu", @"W", @"Th", @"F", @"Sa", @"Su" ] ;
    NSArray * array = [ self collect:^(NSString * dayName){
        return @([ dayNames indexOfObject:dayName ]) ;
    } ] ;
    array = [ array sortedArrayUsingSelector:@selector( compare: ) ] ;
    array = [ array collect:^(NSNumber * index){
        return abbreviations[ [ index integerValue ] ] ;
    }];
    return array ;
}

@end

so... if array has the user's selected day names, you can get the result you want with newArray = [ array arrayBySortingAndAbbreviatingDayNames ]..


edit thought of a much better/simpler way:

NSArray * convertArray(NSArray * input)
{
    NSArray * dayNames = @[ @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", @"Sunday" ] ;
    NSArray * shortDayNames = @[ @"M", @"Tu", @"W", @"Th", @"F", @"Sa", @"Su" ] ;
    NSMutableArray * output = [ NSMutableArray array ] ;
    for( int index=0; index < 7; ++index )
    {
        if ( [ input containsObject:dayNames[ index ]] )
        {
            [ output addObject:shortDayNames[ index ]] ;
        }
    }
    return output ; 
}

edit better yet.

NSArray * ConvertArray(NSArray * input)
{
    NSArray * dayNames = @[ @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", @"Sunday" ] ;
    NSArray * shortDayNames = @[ @"M", @"Tu", @"W", @"Th", @"F", @"Sa", @"Su" ] ;

    return [ shortDayNames objectsAtIndexes:[ dayNames indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [ input containsObject:obj ] ;
    }]] ;
}

...ok, think I'm done. :)

Sign up to request clarification or add additional context in comments.

6 Comments

this code requires exact matching strings, i.e. it won't handle case mismatches. Better would be to use the built-in internationalization stuff so it works on a universal basis.
He did say that the strings are coming from user input, so I don't think that we can provide the abreviations ahead of time like this, but instead need to be calculated based on how many letters that it takes for each one to be unique.
sounds like your UI should present day names, but the data stored should be a day of the week index... then you can use NSDateFormatter to produce localized day short names.
sounds like the user inputs day names?
I guess that isn't what he meant. :-). +1
|
3

Here's another way to do the same thing.

NSArray *input = @[@"Tuesday",@"Friday",@"Wednesday",@"Saturday"];

NSArray *dayArray = @[@{@"Monday":@"M"},@{@"Tuesday":@"Tu"},@{@"Wednesday":@"W"},@{@"Thursday":@"Th"},@{@"Friday":@"F"},@{@"Saturday":@"Sa"},@{@"Sunday":@"Su"}];
NSMutableArray *output = [@[@"",@"",@"",@"",@"",@"",@""] mutableCopy];
for (NSString *aDay in input) {
    NSInteger indx = [dayArray indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [[dayArray[idx] allKeys][0] isEqualToString:aDay];
    }];
    [output replaceObjectAtIndex:indx withObject:dayArray[indx][aDay]];
}
[output removeObjectIdenticalTo:@""];
NSLog(@"%@",output);

1 Comment

Thanks, I always love seeing a second way. I will have to try this one soon.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.