【问题标题】:Get n random objects (for example 4) from nsarray从 nsarray 获取 n 个随机对象(例如 4 个)
【发布时间】:2011-04-30 05:53:43
【问题描述】:

我有一个很大的 NSArray 名称,我需要从该数组中随机获取 4 条记录(名称),我该怎么做?

【问题讨论】:

    标签: objective-c ios random nsarray


    【解决方案1】:
    #include <stdlib.h>
    
    NSArray* names = ...;
    NSMutableArray* pickedNames = [NSMutableArray new];
    
    int remaining = 4;
    
    if (names.count >= remaining) {
        while (remaining > 0) {
           id name = names[arc4random_uniform(names.count)];
    
           if (![pickedNames containsObject:name]) {
               [pickedNames addObject:name];
               remaining--;
           }
        }
    }
    

    【讨论】:

    • 没错,我只是用 arc4random() 替换了 rand(),它更优越,不需要播种。
    • 谢谢,它工作正常。但是,我认为pickNames 应该是 NSMutableArray
    • 是的,确实应该是 NSMutableArray。
    • 这可以针对某些情况进行优化,方法是使名称成为可变数组,并在选择名称后删除名称(然后您也可以取出 containsObject 检查)。想象一下,如果您(例如)有一种情况,您从一个包含 10,001 个成员的数组中挑选 10,000 个项目。在当前答案中,while 循环将执行数千次不成功的迭代。通过这种优化,它将执行零次不成功的迭代。 (显然,在我的极端示例中,一种更有效的方法可能是选择一项并将其删除,但这只是为了说明)
    【解决方案2】:

    我创建了一个名为 NSArray+RandomSelection 的护理。只需将此类别导入项目,然后使用

    NSArray *things = ...
    ...
    NSArray *randomThings = [things randomSelectionWithCount:4];
    

    下面是实现:

    NSArray+RandomSelection.h

    @interface NSArray (RandomSelection)
        - (NSArray *)randomSelectionWithCount:(NSUInteger)count;
    @end
    

    NSArray+RandomSelection.m

    @implementation NSArray (RandomSelection)
    
    - (NSArray *)randomSelectionWithCount:(NSUInteger)count {
        if ([self count] < count) {
            return nil;
        } else if ([self count] == count) {
            return self;
        }
    
        NSMutableSet* selection = [[NSMutableSet alloc] init];
    
        while ([selection count] < count) {
            id randomObject = [self objectAtIndex: arc4random() % [self count]];
            [selection addObject:randomObject];
        }
    
        return [selection allObjects];
    }
    
    @end
    

    【讨论】:

    • 随机选择大于数组的处理不正确。我使用以下而不是前 5 行:if ([self count] &lt; count) { count = [self count]; }
    • 如果数组中的唯一元素少于 'count' 个,你将陷入无限循环
    【解决方案3】:

    如果您更喜欢 Swift 框架,它还具有一些更方便的功能,请随时查看 HandySwift。您可以通过 Carthage 将其添加到您的项目中,然后像这样使用它:

    import HandySwift    
    
    let names = ["Harry", "Hermione", "Ron", "Albus", "Severus"]
    names.sample() // => "Hermione"
    

    还有一个选项可以一次获取多个随机元素

    names.sample(size: 3) // => ["Ron", "Albus", "Harry"]
    

    我希望这会有所帮助!

    【讨论】:

    • 这没有回答问题,因为您需要展示如何使用随机数列表来选择大数组中的名称以创建选择的名称数组。
    • 看来我的回答有误导性。我已将其更新为使用名称数组而不是数字数组作为示例。工作方式相同,只是不同类型的数组。我希望现在很清楚。
    猜你喜欢
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 2015-07-02
    • 1970-01-01
    • 2019-05-03
    相关资源
    最近更新 更多