14

I have an array that looks like this:

let arr = [1,2,3,4,5,6,7,8,9]

I know you can get min and max by:

let min = arr.min()
let max = arr.max()

But how do you get the median?

John S
  • 257
  • 1
  • 3
  • 8

5 Answers5

23

To get the median you can use the following:

let median = arr.sorted(by: <)[arr.count / 2]

In your case it will return 5.

As @Nirav pointed out [1,2,3,4,5,6,7,8] will return 5 but should return 4.5.

Use this instead:

func calculateMedian(array: [Int]) -> Float {
    let sorted = array.sorted()
    if sorted.count % 2 == 0 {
        return Float((sorted[(sorted.count / 2)] + sorted[(sorted.count / 2) - 1])) / 2
    } else {
        return Float(sorted[(sorted.count - 1) / 2])
    }
}

Usage:

let array = [1,2,3,4,5,6,7,8]
let m2 = calculateMedian(array: array) // 4.5
Rashwan L
  • 38,237
  • 7
  • 103
  • 107
  • Using `sorted` causes the algorithm to take O(*n* log *n*) time. If performance is important, opt for an [algorithm that completes in O(*n*) time](https://stackoverflow.com/a/71705133/145173). – Edward Brey Jun 27 '22 at 13:29
12

The median is defined as the number in the middle of the sequence. If there is not one middle number, then it's the average of the two middle numbers.

extension Array where Element == Int {
    func median() -> Double {
        let sortedArray = sorted()
        if count % 2 != 0 {
            return Double(sortedArray[count / 2])
        } else {
            return Double(sortedArray[count / 2] + sortedArray[count / 2 - 1]) / 2.0
        }
    }
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
6

Note that if the array is empty, the median is undefined. So a safe median function returns an optional, just like the min() and max() built-in methods do.

extension Array where Element == Int {
    func median() -> Double? {
        guard count > 0  else { return nil }

        let sortedArray = self.sorted()
        if count % 2 != 0 {
            return Double(sortedArray[count/2])
        } else {
            return Double(sortedArray[count/2] + sortedArray[count/2 - 1]) / 2.0
        }
    }
}

With that defined, you can write:

if let median = arr.median() {
    // do something
}
Robin Stewart
  • 3,147
  • 20
  • 29
1

If someone (like me) likes two*-liners:

let sorted = arr.sorted(by: <)
let median = Double(sorted[arr.count/2] + sorted.reversed()[arr.count/2])/2.0
Joakim Poromaa Helger
  • 1,261
  • 10
  • 17
0

Algorithms that use sorted take O(n log n) time. That's typically not a problem for 9 numbers, but if your array is large, use an algorithm that completes in O(n) time. An example is this k-th largest element algorithm. It recursively partitions the array, but doesn’t have to go through all the work to sort it, so it’s much faster.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253