如何在NSArray中找到NSNumbers的中位数值?

13

我试图计算一个包含 NSNumbers 的 NSArray 中(小)集合的中位数。NSArray 中的每个对象都是 NSNumber。

这是我尝试的代码,但它没有起作用:

NSNumber *median = [smallNSArray valueForKeyPath:@"@median.floatValue"];
3个回答

25
NSArray *sorted = [smallNSArray sortedArrayUsingSelector:@selector(compare:)];    // Sort the array by value
NSUInteger middle = [sorted count] / 2;                                           // Find the index of the middle element
NSNumber *median = [sorted objectAtIndex:middle];                                   // Get the middle element
你可以更进一步。例如,对于一个由偶数个数字组成的集合,中位数在技术上是中间两个数字的平均值。你还可以将其封装到 NSArray 的类别中,以创建一个整洁的单行方法:
你可以做得更好。例如,一个有偶数个数字的集合的中位数在技术上是中间两个数字的平均值。你还可以在 NSArray 的类别中封装它为一个整洁的单行方法:
@interface NSArray (Statistics)
- (id)median;
@end

@implementation NSArray (Statistics)

- (id)median
{
    return [[self sortedArrayUsingSelector:@selector(compare:)] objectAtIndex:[self count] / 2];
}

@end

6

如果有人有这种不寻常的需求,以下是一个适用于数组元素数量为奇数或偶数的类别方法。

NSArray 类别方法

- (float)median {
    if (self.count == 1) return [self[0] floatValue];

    float result = 0;
    NSUInteger middle;

    NSArray * sorted = [self sortedArrayUsingSelector:@selector(compare:)];
    if (self.count % 2 != 0) {  //odd number of members
        middle = (sorted.count / 2);
        result = [[sorted objectAtIndex:middle] floatValue];
    }
    else {
        middle = (sorted.count / 2) - 1;
        result = [[@[[sorted objectAtIndex:middle], [sorted objectAtIndex:middle + 1]] valueForKeyPath:@"@avg.self"] floatValue];
    }
    return result;
}

测试

NSArray * singleElement = @[@1];
NSArray * oddNumberOfElements = @[@3, @5, @7, @12, @13, @14, @19, @20, @21, @22, @23, @29, @39, @40, @56];
NSArray * evenNumberOfElements = @[@3, @5, @7, @12, @13, @14, @19, @20, @21, @22, @23, @29, @40, @56];

NSLog(
    @"oddNumberOfElements: %f, evenNumberOfElements: %f singleElement: %f",
    [oddNumberOfElements median], [evenNumberOfElements median], [singleElement median]
);
//oddNumberOfElements: 20.000000, evenNumberOfElements: 19.500000 singleElement: 1.000000

你在奇数情况下选择了错误的索引,更糟糕的是,当数组长度为1时,代码会崩溃。 - JKvr
@JKvr,谢谢!粗心大意...修改了方法并添加了测试代码。 - shmim

3

Swift扩展

extension Array where Element: Comparable {

  var median: Element {
    return self.sort(<)[self.count / 2]
  }

}

正如上面有些人所说,对于偶数个项,这种方法将无法正确工作。 - smat88dd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接