说我有NSArray
:
@[@"Hello", @"World", @"Hello"]
由于有两个'Hello',我需要将数组转换为:
@[@"Hello(1)", @"World", @"Hello(2)"]
所以'你好'附加了数字,但'世界'不会附加(1)因为只有一个。
我知道我可以使用单词作为键创建一个字典并遍历数组,将计数增加为它们的值,但是有更好的方法吗?
编辑:
是的我确实需要结果数组与输入数组具有相同的单词顺序,原因是我正在为非英语学生制作词汇应用程序,其中一项功能是翻译(用他们自己的语言)句子和句子的混洗单词列表,然后他们可以从列表中以正确的顺序选择单词。所以你可能会看到'你好吗?'的翻译用另一种语言和单词列表:'做'你'怎么''做',学生需要按照'你怎么做'的顺序选择单词,这就是我需要区分顺序的原因同样的话。
答案 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)"
)