Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write the Average Function for this Data structure in Scheme/Lisp?

I want to find the price of a new-item based on the average prices of similar items. The function get-k-similar uses k-Nearest Neighbors but returns me this output ((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))

I need to find the average PRICE of the similar items. i.e Average of 117 and 75. Is there a better way to iterate? My function looks too ugly.

(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)))
like image 674
unj2 Avatar asked Mar 01 '23 12:03

unj2


2 Answers

Common Lisp

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

or

(loop for ((nil nil e) . nil) in a-list
      count e into length
      sum e into sum
      finally (return (/ sum length)))
like image 190
Rainer Joswig Avatar answered Apr 28 '23 11:04

Rainer Joswig


You can do the simple thing and just pull out every third value:

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

This is a little inefficient since it builds an intermediate list, and my guess is that this is why you tried foldl. Here's the right way to do that:

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

There is still a minor inefficiency -- length is doing a second scan -- but that's something that you shouldn't bother about since you'd need some really long lists to get any visible slowdown.

like image 31
Eli Barzilay Avatar answered Apr 28 '23 10:04

Eli Barzilay