NSArray에서 임의의 개체 선택


83

객체 1, 2, 3 및 4 가있는 배열이 있다고 가정 해 보겠습니다. 이 배열에서 임의의 객체를 어떻게 선택합니까?


여기에있는 모든 답변은 정확하지만 최신 솔루션은 여기에서 내 답변을 참조 하십시오 . arc4random_uniform모듈로 바이어스를 피하기 위해 방법을 사용합니다 .
Adam

이 질문에 대한 답은 아니지만 흥미로운 점입니다. 다른 Foundation 컬렉션 (NSSet NSHashTable)에는 Set / HashTable에서 임의의 (무작위) 개체를 읽는 "anyObject"메서드가 있습니다. 아래 제안에 따라 NSArray에 대한 확장으로이 메서드를 구현할 수 있습니다.
Motti Shneor

답변:


192

@Darryl의 대답은 정확하지만 약간의 조정을 사용할 수 있습니다.

NSUInteger randomIndex = arc4random() % theArray.count;

수정 :

  • arc4random()over rand()and 사용 random()은 시드 ( srand()또는 호출 srandom())가 필요하지 않기 때문에 더 간단합니다 .
  • 모듈로 연산자는 ( %또한 의미 명확하면서), 전체 문 짧은합니다.

27
arc4random man 페이지에서 : arc4random_uniform ()은 상한이 2의 거듭 제곱이 아닐 때 "모듈로 바이어스"를 피하므로`ʻarc4random () % upper_bound ''와 같은 구성보다 권장됩니다.
Max Yankov 2012-06-15

@collibhoy 아니, 때문에 0 % 4 = 0, 1 % 4 = 1, 2 % 4 = 2, 3 % 4 = 3, 4 % 4 = 0, 5 % 4 = 1당신이에 의해 모듈로하면 ... N , 가장 큰 결과보다 클 수 없으며 N-1 .
Dave DeLong 2015

1
소스 코드에 따르면 @DaveDeLong, count속성은 다음과 같습니다@interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> @property (readonly) NSUInteger count;
mikeho

17

이것이 제가 생각해 낼 수있는 가장 간단한 해결책입니다.

id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)];

그것은 확인하는 것이 필요 count비 때문에 nil하지만 비어 NSArray반환 0을 위해 count, 그리고 arc4random_uniform(0)돌아갑니다 0. 따라서 확인하지 않으면 배열의 경계를 벗어납니다.

이 솔루션은 유혹적이지만 빈 배열로 인해 충돌이 발생하기 때문에 잘못 되었습니다.

id object = array[arc4random_uniform(array.count)];

참고로 다음은 문서입니다 .

u_int32_t
arc4random_uniform(u_int32_t upper_bound);

arc4random_uniform() will return a uniformly distributed random number less than upper_bound.

남자 페이지는 언급하지 않는 arc4random_uniform반환 0하는 경우 0로 전달됩니다 upper_bound.

또한에 arc4random_uniform정의되어 <stdlib.h>있지만 #importiOS 테스트 프로그램 에서는을 추가 할 필요가 없습니다.


11

아마도 다음과 같은 내용 일 것입니다.

NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]);

난수 생성기 (예 : srandomdev ())를 초기화하는 것을 잊지 마십시오.

참고 : 아래 답변에 따라 점 구문 대신 -count를 사용하도록 업데이트했습니다.


9
@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

편집 : Xcode 7에 대해 업데이트되었습니다. Generics, nullability


1

난수를 생성하여 색인으로 사용합니다. 예:

#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;
}

@Joshua 좀 더 자세히 알고 싶다면 SecRandomCopyBytes()어쨌든 iPhone에서 암호 학적으로 유용한 난수를 얻는 데 사용할 수 있습니다 . Mac에서는 / dev / random에 직접 액세스 할 수 있습니다.

질문의 요점은 배열에서 임의의 항목을 선택하는 방법을 보여주는 것이며이 답변은 실제로 최상의 정보를 제공하지 않습니다.
beakr

나는이 농담을 아주 좋아하지만 그것을 이해하지 못하는 사람들을 돕기 위해 투표했다.
Stig Brautaset

0
 srand([[NSDate date]  timeIntervalSince1970]);

 int inx =rand()%[array count];

inx는 난수입니다.

여기서 srand ()는 임의 선택 함수 이전에 프로그램의 어느 위치 에나있을 수 있습니다.


0
ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))];

그것을 int로 캐스트하고 싶다면 여기에 대한 해결책이 있습니다 (열거 호출을 무작위 화하는 경우 등 비 순차적 숫자 배열에서 임의의 정수가 필요할 때 유용합니다)

int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue];

0

Swift 4 :

let array = ["one","two","three","four"]
let randomNumber = arc4random_uniform(UInt32(array.count))

array[Int(randomNumber)]

1
좋은 답변을 작성하는 방법을 검토하십시오 . 코드 전용 답변은 질문에서 문제를 해결하는 방법을 설명하지 않기 때문에 권장하지 않습니다. 당신이 수행하고이 7 살짜리 질문 이미 많은 답변에 개선하는 방법이 무엇인지 설명하는 답변을 업데이트해야합니다
FluffyKitten
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.