Как написать функцию усреднения для этой структуры данных в Scheme / Lisp? - PullRequest
4 голосов
/ 17 июля 2009

Я хочу узнать цену новинки на основе средних цен на аналогичные товары. Функция get-k-Similar использует k-Nearest Neighbors, но возвращает мне этот вывод ((list rating age price) proximity).

For example, 2-similar would be:
(((5.557799748150248 3 117.94262493533647) . 3.6956648993026904)
 ((3.0921378389849963 7 75.61492560596851) . 5.117886776721699))

Мне нужно найти среднюю ЦЕНУ подобных предметов. т.е. в среднем 117 и 75. Есть ли лучший способ итерации? Моя функция выглядит слишком некрасиво.

(define (get-prices new-item)

  (define (average-prices a-list)
    (/ (cdr 
        (foldl (λ(x y) (cons (list 0 0 0)
                             (+ (third (car x)) (third (car y))))) 
               (cons (list 0 0 0) 0)
               a-list))
        (length a-list)))

    (let ((similar-items (get-k-similar new-item)))
      (average-prices similar-items)))

Ответы [ 2 ]

5 голосов
/ 17 июля 2009

Common Lisp

(/ (reduce '+ a-list :key 'caddar) (length a-list))

или

(loop for ((nil nil e) . nil) in a-list
      count e into length
      sum e into sum
      finally (return (/ sum length)))
3 голосов
/ 17 июля 2009

Вы можете сделать простую вещь и просто извлечь каждое третье значение:

(define (average-prices a-list)
  (/ (apply + (map fourth a-list)) (length a-list)))

Это немного неэффективно, поскольку он создает промежуточный список, и я предполагаю, что именно поэтому вы попытались foldl. Вот правильный способ сделать это:

(define (average-prices a-list)
  (/ (foldl (lambda (x acc) (+ (third x) acc)) 0 l)
     (length a-list)))

Все еще есть небольшая неэффективность - length выполняет второе сканирование - но это то, о чем вам не стоит беспокоиться, поскольку вам понадобятся несколько действительно длинных списков, чтобы получить какие-либо видимые замедление.

...