1

说我有一个NSArray

@[@"Hello", @"World", @"Hello"]

由于有两个'Hello',我需要将数组转换为:

@[@"Hello(1)", @"World", @"Hello(2)"]

所以“Hello”附加了数字,但“World”不会附加 (1),因为只有一个。

我知道我可以创建一个以单词为键的字典并遍历数组,将计数作为它们的值递增,但有更好的方法吗?

编辑:

是的,我确实需要结果数组与输入数组的单词顺序相同,原因是我正在为非英语学生制作词汇应用程序,其中一个功能是翻译(在他们自己的语言)的句子和句子的打乱单词列表,然后他们可以从列表中以正确的顺序选择单词。所以你可能会看到“你好吗?”的翻译。在另一种语言和单词列表中:'do''you''how''do',学生需要按照'How do you do?'的顺序选择单词,这就是为什么我需要区分顺序相同的词。

4

2 回答 2

2

也许使用一个NSCountedSet(这相当于你可能用 实现的NSDictionary

-(NSArray*)renameStrings:(NSArray*)strings
{
    NSCountedSet * set = [ [ NSCountedSet alloc ] initWithArray:strings ];

    NSMutableArray * result = [ NSMutableArray arrayWithCapacity:[ strings count ] ] ;

    for( id object in set )
    {
        NSUInteger count = [ set countForObject:object ] ;
        if ( count == 1 )
        {
            [ result addObject:object ] ;
        }
        else
        {
            NSUInteger index= 0 ;
            while( index < count )
            {
                ++index ;
                [ result addObject:[ NSString stringWithFormat:@"%@(%lu)", object, index ] ] ;
            }
        }
    }

    return result ;
}

(结果的排序可能与输入不同)

附录:

这是一个一次性解决方案,它也保持输入的顺序(只是为了“有趣”):

struct Tree
{
    struct Tree * left ;
    struct Tree * right ;
    NSUInteger count ;
    NSUInteger firstIndex ;
    CFStringRef value ;
};

void TreeInsert( struct Tree * tree, NSMutableArray * resultArray, NSString * stringToInsert, NSUInteger stringIndex )
{
    switch( CFStringCompare( (__bridge CFStringRef)stringToInsert , tree->value, 0 ) )
    {
        case NSOrderedAscending:
        {
            if ( tree->right )
            {
                TreeInsert( tree->right, resultArray, stringToInsert ,stringIndex ) ;
            }
            else
            {
                tree->right = malloc( sizeof( struct Tree ), 1 ) ;
                *tree->right = (struct Tree){ NULL, NULL, 1, stringIndex, CFBridgingRetain( stringToInsert ) } ;
                [ resultArray addObject:stringToInsert ] ;
            }
            break ;
        }
        case NSOrderedDescending:
        {
            if ( tree->left )
            {
                TreeInsert( tree->left, resultArray, stringToInsert ,stringIndex ) ;
            }
            else
            {
                tree->left = malloc( sizeof( struct Tree ), 1 ) ;
                *tree->left = (struct Tree){ NULL, NULL, 1, stringIndex, CFBridgingRetain( stringToInsert ) } ;
                [ resultArray addObject:stringToInsert ] ;
            }
            break ;
        }
        default:
        {
            ++tree->count ;
            if ( tree->firstIndex != NSNotFound )
            {
                NSString * string = [ NSString stringWithFormat:@"%@(1)", [ resultArray objectAtIndex:tree->firstIndex ] ] ;
                [ resultArray replaceObjectAtIndex:tree->firstIndex withObject:string ] ;
                tree->firstIndex = NSNotFound ;
            }
            [ resultArray addObject:[ NSString stringWithFormat:@"%@(%lu)", stringToInsert, tree->count ] ] ;
            break ;
        }
    }
}

void DisposeTree( struct Tree * tree )
{
    if ( tree->left ) { DisposeTree( tree->left ) ; }
    if ( tree->right ) { DisposeTree( tree->right ) ; }
    if ( tree->value ) { CFRelease( tree->value ) ; }

    free( tree ) ;
}

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

    @autoreleasepool {

        NSArray * array = @[ @"Hello", @"Goodbye", @"Hello", @"Something else" ] ;
        NSMutableArray * result = [ NSMutableArray arrayWithCapacity:array.count ] ;

        struct Tree * tree = NULL ;

        NSEnumerator * enumerator = [ array objectEnumerator ] ;

        {
            NSString * firstString = [ enumerator nextObject ] ;
            tree = malloc( sizeof( struct Tree ), 1 ) ;
            *tree = (struct Tree){ NULL, NULL, 1, 0, CFBridgingRetain( firstString ) } ;
            [ result addObject:firstString ] ;
        }

        NSUInteger index = 1 ;
        for( NSString * string in enumerator )
        {
            TreeInsert( tree, result, string, index ) ;
            ++index ;
        }

        NSLog(@"result=%@\n", result ) ;
    }
}
于 2013-08-25T00:59:37.703 回答
1

NSCountedSet绝对是要走的路。如果你使用其中的两个,你可以一次完成:一个知道总共有多少,一个跟踪你到目前为止看到的数量:

NSArray *a = @[@"Hello", @"World", @"Hello"];
NSCountedSet *counts = [NSCountedSet setWithArray:a];

NSMutableArray *final = [NSMutableArray array];
NSCountedSet *countsSoFar = [NSCountedSet set];

for (NSString *str in a) {
    if ([counts countForObject:str] > 1) {
        // this object appears more than once.  append the number of times it's appeared so far
        [countsSoFar addObject:str];
        NSUInteger countSoFar = [countsSoFar countForObject:str];
        str = [str stringByAppendingFormat:@"(%ld)", countSoFar];
    }
    [final addObject:str];
}

NSLog(@"%@", final);

这记录:

(
  "Hello(1)",
  World,
  "Hello(2)"
)
于 2013-08-25T04:59:26.823 回答