Cocoa NSMutableSet和NSArray排序,如何保持一致?

Cocoa NSMutableSet和NSArray排序,如何保持一致?,cocoa,nsarray,Cocoa,Nsarray,我试图以随机、不重复的顺序创建一个对象数组。按照此处的建议,将NSMutableSet用于重型起重: 我在创建后将它们转储到NSArray中以访问它们,但NSArray并没有按照我在NSMutableSet中放置它们的顺序保留。更令人困惑的是,它并不一致 我的代码: NSArray *puzzleImages = [[NSArray alloc] initWithObjects:@"elephant.png", @"gorilla.png", @"lion.png", @"zebra.png",

我试图以随机、不重复的顺序创建一个对象数组。按照此处的建议,将NSMutableSet用于重型起重:

我在创建后将它们转储到NSArray中以访问它们,但NSArray并没有按照我在NSMutableSet中放置它们的顺序保留。更令人困惑的是,它并不一致

我的代码:

NSArray *puzzleImages = [[NSArray alloc] initWithObjects:@"elephant.png", @"gorilla.png", @"lion.png", @"zebra.png", @"flamingo.png", @"hyena.png", @"seal.png", @"hippo.png", @"rhino.png", @"tiger.png", @"macaw.png", @"bear.png", nil];

NSArray *puzzleSounds = [[NSArray alloc] initWithObjects:@"elephant", @"gorilla", @"lion", @"zebra", @"flamingo", @"hyena", @"seal", @"hippo", @"rhino", @"tiger", @"macaw", @"bear", nil];

NSMutableSet *aImages1 = [NSMutableSet setWithCapacity:2];
NSMutableSet *aSounds1 = [NSMutableSet setWithCapacity:2];
NSMutableSet *aValues1 = [NSMutableSet setWithCapacity:2];
while([aImages1 count]<=1){
  int Randnum1 = arc4random() % 11;
  [aImages1 addObject:[puzzleImages objectAtIndex:Randnum1]];
  [aSounds1 addObject:[puzzleSounds objectAtIndex:Randnum1]];
  [aValues1 addObject:[NSNumber numberWithInt:Randnum1]];
  NSLog(@"image:%@, sound:%@, value:%@",[puzzleImages objectAtIndex:Randnum1],[puzzleSounds objectAtIndex:Randnum1],[NSNumber numberWithInt:Randnum1]);
} 

NSArray *arrayOfImages1 = [aImages1 allObjects];
NSLog(@"arrayOfImages1: %@",arrayOfImages1);

NSArray *arrayOfSounds1 = [aSounds1 allObjects];
NSLog(@"arrayOfSounds1: %@",arrayOfSounds1);

NSArray *arrayOfValues1 = [aValues1 allObjects];
NSLog(@"aValues1: %@",aValues1);

金刚鹦鹉的声音怎么会超过狮子的声音?当然,这种情况并不总是发生,但一旦发生就会打破游戏。我确信我遗漏了一些愚蠢的东西,但我花了足够多的时间试图自己解决它。

集合没有顺序-因此,如果你想保持你添加的东西的顺序不变,你需要使用数组


同样,在这种情况下,如果原始数组中有两个相同的项,则从集合中获得的元素会更少。

集合没有顺序-因此,如果要使添加的内容保持相同的顺序,则需要使用数组


同样,在这种情况下,如果原始数组中有两个相同的项,则从集合中获得的元素将更少。

集合不按顺序排列。特别是,从它们中获得的顺序将取决于放入的对象,而不是添加它们的顺序。(它们通常是使用某种对象散列实现的,尽管我不知道这里是否是这种情况。)

由于您希望保持一组项目的链接,一个选项是创建一个包含所有项目的单一对象类,并将其存储在集合中。然后,您可以将其取出并读取其不同字段

另一种选择是只对一个索引列表进行置乱,然后按该顺序访问各种原始数组中的对象

更新:你链接到的帖子解决了一个与你截然不同的问题。在您的情况下,使用集合排序进行随机操作确实是错误的,因为排序实际上不是随机的。正确的做法是对单个索引数组进行置乱,如下所示:

NSMutableArray *indices = [NSMutableArray arrayWithCapacity:11];
for ( int i = 0; i < 11; ++i )
    [indices addObject:[NSNumber numberWithInt:i]];
for ( int i = 0; i < 11; ++i )
    [indices exchangeObjectAtIndex:i withObjectAtIndex:(arc4random() % 11)];

NSLog(@"First random image: %@", [puzzleImages objectAtIndex:[[indices objectAtIndex:0] intValue]]);
NSMutableArray*索引=[NSMutableArray阵列容量:11];
对于(int i=0;i<11;++i)
[索引添加对象:[NSNumber numberWithInt:i]];
对于(int i=0;i<11;++i)
[索引交换对象索引:i与对象索引:(arc4random()%11)];
NSLog(@“第一个随机图像:%@,[puzzleImages对象索引:[[Indexes对象索引:0]intValue]]);

等等。唯一性的保证来自这样一个事实,即您从列表中的索引0..10开始,然后进行无序排列,而不是试图从可能产生重复的随机数生成器中变出索引本身。

集合没有顺序。特别是,从它们中获得的顺序将取决于放入的对象,而不是添加它们的顺序。(它们通常是使用某种对象散列实现的,尽管我不知道这里是否是这种情况。)

由于您希望保持一组项目的链接,一个选项是创建一个包含所有项目的单一对象类,并将其存储在集合中。然后,您可以将其取出并读取其不同字段

另一种选择是只对一个索引列表进行置乱,然后按该顺序访问各种原始数组中的对象

更新:你链接到的帖子解决了一个与你截然不同的问题。在您的情况下,使用集合排序进行随机操作确实是错误的,因为排序实际上不是随机的。正确的做法是对单个索引数组进行置乱,如下所示:

NSMutableArray *indices = [NSMutableArray arrayWithCapacity:11];
for ( int i = 0; i < 11; ++i )
    [indices addObject:[NSNumber numberWithInt:i]];
for ( int i = 0; i < 11; ++i )
    [indices exchangeObjectAtIndex:i withObjectAtIndex:(arc4random() % 11)];

NSLog(@"First random image: %@", [puzzleImages objectAtIndex:[[indices objectAtIndex:0] intValue]]);
NSMutableArray*索引=[NSMutableArray阵列容量:11];
对于(int i=0;i<11;++i)
[索引添加对象:[NSNumber numberWithInt:i]];
对于(int i=0;i<11;++i)
[索引交换对象索引:i与对象索引:(arc4random()%11)];
NSLog(@“第一个随机图像:%@,[puzzleImages对象索引:[[Indexes对象索引:0]intValue]]);

等等。你对唯一性的保证来自这样一个事实:你从列表中的索引0..10开始,然后洗牌,而不是试图从一个可能产生重复的随机数生成器中变出索引本身。

我没有看到任何你说“推荐此处”的链接。我没有看到任何你说“推荐此处”的链接。我不使用数组的原因是存在重复的风险。没有内置的“保持它们唯一性”检查器,就像在一个集合中一样。我确信我可以在添加对象之前检查数组中是否存在该对象,但我试图避免这样做。您只需将
-containsObject:
发送到数组中,查看它是否已经存在。因此,这并没有太多额外的工作(对您来说,可能会对大型阵列的性能产生影响)。我不使用阵列的原因是存在重复的风险。没有内置的“保持它们唯一性”检查器,就像在一个集合中一样。我确信我可以在添加对象之前检查数组中是否存在该对象,但我试图避免这样做。您只需将
-containsObject:
发送到数组中,查看它是否已经存在。因此,这并没有太多额外的工作(对您来说,可能会对大型阵列的性能产生影响)。我已经尝试过了,但不知道如何访问集合中的对象。例如,我将创建一个NSMutableSet*RandomSetOfNumber,然后获取每个,并创建一个包含所需对象的数组。也许我走错方向了?我也是obj-c的新手,所以我可能在你的解释中遗漏了一些东西。@Lawrence请参阅更新。不要用电视机,这里不合适。从索引列表中获取唯一性保证,然后相应地访问其他内容。这是有意义的,代码也是有意义的。我想我是在尝试集合,因为它似乎能很快解决问题。但是,当我尝试运行您的代码时,我得到了一个无效的操作数到二进制%error。@Lawrence:Oops-我错过了
arc4random()上的函数调用括号