Angenommen, ich habe ein Array mit den Objekten 1, 2, 3 und 4. Wie würde ich ein zufälliges Objekt aus diesem Array auswählen?
Angenommen, ich habe ein Array mit den Objekten 1, 2, 3 und 4. Wie würde ich ein zufälliges Objekt aus diesem Array auswählen?
Antworten:
@ Darryls Antwort ist richtig, könnte aber einige kleinere Änderungen gebrauchen:
NSUInteger randomIndex = arc4random() % theArray.count;
Änderungen:
arc4random()
over rand()
und random()
ist einfacher, da kein Seeding (Aufruf srand()
oder srandom()
) erforderlich ist .%
) verkürzt die Gesamtanweisung und macht sie gleichzeitig semantisch klarer.0 % 4 = 0
, 1 % 4 = 1
, 2 % 4 = 2
, 3 % 4 = 3
, 4 % 4 = 0
, 5 % 4 = 1
... Falls Sie mit dem Modulo n , Ihr größten Ergebnis wird nie größer sein als n-1 .
count
ist eine Eigenschaft:@interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> @property (readonly) NSUInteger count;
Dies ist die einfachste Lösung, die ich finden könnte:
id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)];
Es ist zu prüfen , count
weil ein nicht nil
aber leer NSArray
zurückkehren wird 0
für count
und arc4random_uniform(0)
kehrt 0
. Ohne die Überprüfung werden Sie also die Grenzen des Arrays überschreiten.
Diese Lösung ist verlockend, aber falsch, da sie einen Absturz mit einem leeren Array verursacht:
id object = array[arc4random_uniform(array.count)];
Als Referenz finden Sie hier die Dokumentation :
u_int32_t
arc4random_uniform(u_int32_t upper_bound);
arc4random_uniform() will return a uniformly distributed random number less than upper_bound.
In der Manpage wird nicht erwähnt, dass arc4random_uniform
zurückgegeben wird, 0
wenn 0
als übergeben wird upper_bound
.
Auch arc4random_uniform
ist in definiert <stdlib.h>
, aber das Hinzufügen #import
war in meinem iOS-Testprogramm nicht notwendig.
Vielleicht etwas in der Art von:
NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]);
Vergessen Sie nicht, den Zufallszahlengenerator (z. B. srandomdev ()) zu initialisieren.
HINWEIS: Ich habe gemäß der folgenden Antwort die Verwendung von -count anstelle der Punktsyntax aktualisiert.
@interface NSArray<ObjectType> (Random)
- (nullable ObjectType)randomObject;
@end
@implementation NSArray (Random)
- (nullable id)randomObject
{
id randomObject = [self count] ? self[arc4random_uniform((u_int32_t)[self count])] : nil;
return randomObject;
}
@end
Bearbeiten: Aktualisiert für Xcode 7. Generika, Nullbarkeit
Generieren Sie eine Zufallszahl und verwenden Sie sie als Index. Beispiel:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSArray *array = [NSArray arrayWithObjects: @"one", @"two", @"three", @"four", nil];
NSUInteger randomNumber;
int fd = open("/dev/random", O_RDONLY);
if (fd != -1) {
read(fd, &randomNumber, sizeof(randomNumber));
close(fd);
} else {
fprintf(stderr, "Unable to open /dev/random: %s\n", strerror(errno));
return -1;
}
double scaledRandomNumber = ((double)randomNumber)/NSUIntegerMax * [array count];
NSUInteger randomIndex = (NSUInteger)floor(scaledRandomNumber);
NSLog(@"random element: %@", [array objectAtIndex: randomIndex]);
}
return 0;
}
SecRandomCopyBytes()
auf dem iPhone ohnehin kryptografisch nützliche Zufallszahlen abrufen . Auf dem Mac haben Sie direkten Zugriff auf / dev / random.
srand([[NSDate date] timeIntervalSince1970]);
int inx =rand()%[array count];
Inx ist die Zufallszahl.
Dabei kann srand () an einer beliebigen Stelle im Programm vor der Zufallsauswahlfunktion stehen.
ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))];
Wenn Sie dies in ein int umwandeln möchten, finden Sie hier die Lösung dafür (nützlich, wenn Sie ein zufälliges int aus einem Array nicht sequentieller Zahlen benötigen, wenn Sie einen Aufzählungsaufruf randomisieren usw.).
int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue];
In Swift 4:
let array = ["one","two","three","four"]
let randomNumber = arc4random_uniform(UInt32(array.count))
array[Int(randomNumber)]
arc4random_uniform
Methode, um Modulo Bias zu vermeiden.