ObjC:数组中每个字符串的计数?

时间:2013-08-25 00:47:45

标签: ios objective-c nsarray

说我有NSArray

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

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

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

所以'你好'附加了数字,但'世界'不会附加(1)因为只有一个。

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

编辑:

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

2 个答案:

答案 0 :(得分: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 ) ;
    }
}

答案 1 :(得分: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)"
)