方案 - 从已排序列表中的中位数列表中获取中位数

Scheme - Get median from a list of median from already sorted list

我试图创建的程序是一个可以执行从平均值到 std-dev 等一系列数学函数的程序,但我被绊倒的是中值。该列表已经排序,所以我怎样才能得到这个列表的长度来确定是偶数还是奇数,然后从中得到中位数。当前代码如下。 Scheme 很新,所以语法对我来说仍然很混乱。

代码

(define make-tswb
  (lambda ()
    (let ((records '()))
      (lambda (command . args)
        (cond
          ((equal? command 'empty?)
           (null? records))
          ((equal? command 'add!)
           (set! records (cons (car args) records)))
          ((equal? command 'get)
           (letrec ((sort-records (lambda (r) (sort r (lambda (x y) (<= (car x) (car y)))))))
             (if (null? args)
                 (sort-records records)
                 (sort-records (filter(car args) records)))))
          ((equal? command 'analytic)
           (cond
             ((= (length args) 1)
              ((car args) records))
             ((= (length args) 2)
              ((car args) (filter (cadr args) records))))))))))


(define listofVal
  (lambda (lst)
    (if (null? lst)
        '()
        (sort (map cadddr lst) <))))

(define median
  (lambda (medianList)
    (let ((values (listofVal medianList)))
      (let ((len (length medianList)))
      // ??????????


(define tswb (make-tswb))
(tswb 'add!     '(2 123 "temp1"  76.1))
(tswb 'add!     '(1 123 "temp1"  72.0))
(tswb 'add!     '(1 123 "temp1"  75.0))
(tswb 'analytic median)

根据this page,你需要处理两种情况:

  1. 列表的长度为偶数。
  2. 不是偶数

第一种情况,需要取中间的两个值,求和再除以二。对于第二种情况,你需要找到排序列表的中间值,这个值将是中位数。

所以,我认为这对你有用:

(define (count-median-for-even len listOfVal)
  (/ (+ (list-ref listOfVal (round (- (/ len 2) 1)))
        (list-ref listOfVal (round (/ len 2)))) 2))

(define (count-median-for-odd len listOfVal)
  (list-ref listOfVal (round (/ len 2))))

(define median
  (lambda (medianList)
    (let ((values (listofVal medianList)))
      (let ((len (length medianList)))
        (if (even? len) (count-median-for-even len values) (count-median-for-odd len values))))))

在上面 link 的三个测试用例上测试了这个,我可以说这一定能满足你的需求。