2

我有一个输入是这种形式:

(((lady-in-water . 1.25)
  (snake . 1.75)
  (run . 2.25)
  (just-my-luck . 1.5))
 ((lady-in-water . 0.8235294117647058)
  (snake . 0.5882352941176471)
  (just-my-luck . 0.8235294117647058))
 ((lady-in-water . 0.8888888888888888)
  (snake . 1.5555555555555554)
  (just-my-luck . 1.3333333333333333)))

(上下文:单词表示电影,数字表示用户提交的加权评分)

我需要添加所有数量并返回一个看起来像这样的列表

((lady-in-water 2.5)
 (snake 2.5)
 (run   2.25)
 (just-myluck 2.6))

如何遍历列表和所有数量?我真的很难过。请帮我。

谢谢。

4

4 回答 4

2

我的做法和上面的怀远类似,但是我更喜欢用dolist来循环:

(defun parse-ratings (all-ratings)
  (let ((hash (make-hash-table)))
    (dolist (rating-list all-ratings)
      (dolist (rating rating-list)
        (incf (gethash (car rating) hash 0)
              (cdr rating))))
    (maphash (lambda (key value) 
               (format t "total for ~a: ~a~%" key value))
             hash)))

这导致以下输出:

CL-USER> (parse-ratings '(((lady-in-water . 1.25) (snake . 1.75) 
                          (run . 2.25) (just-my-luck . 1.5))
                         ((lady-in-water . 0.8235294117647058) 
                          (snake . 0.5882352941176471) 
                          (just-my-luck . 0.8235294117647058))
                         ((lady-in-water . 0.8888888888888888)
                          (snake . 1.5555555555555554) 
                          (just-my-luck . 1.3333333333333333))))
total for LADY-IN-WATER: 2.9624183
total for SNAKE: 3.893791
total for RUN: 2.25
total for JUST-MY-LUCK: 3.6568627
NIL
CL-USER> 
于 2009-07-12T00:45:46.333 回答
1

您需要将问题分为两部分:首先,将列表转换为如下内容:

'(((lady-in-water . 1.25) (lady-in-water . 0.82) (lady-in-water . 0.88))
  ((snake . 1.75) ...)
  ...)

我会这样做transpose

(define (transpose ls)
  (if (null? (car ls))
      '()
      (cons (map car ls) (transpose (map cdr ls)))))

然后很容易将转置后的电影列表简化为单个对列表:

 (define (sum-movie movie)
   (cons (caar movie) (apply + (map cdr movie))))
 (define (sum-movies movies)
   (map sum-movie (transpose movies)))

请注意,这transpose是不安全的:如果您在一个子列表中缺少一部电影,它将崩溃。此外,transpose首先使用假设电影每次都以相同的顺序出现。

于 2009-07-11T21:37:23.720 回答
1

在 Common Lisp 中:

(defun marginalize (data)
  (let ((table (make-hash-table)))
    (loop for row in data do
      (loop for (k . v) in row do
        (incf (gethash k table 0.0) v)))
    (loop for k being the hash-key of table using (hash-value v)
          collect (cons k v))))
于 2009-07-11T22:31:15.593 回答
1

为了避免 CL 在任何方面都优越的错误印象,这里有一个使用哈希表方法的 PLT Scheme 解决方案。我添加了一个sort结果以获得额外的信用。

(define (data->movies data)
  (define t (make-hasheq))
  (for* ([x (in-list data)] [x (in-list x)])
    (hash-set! t (car x) (+ (cdr x) (hash-ref t (car x) 0))))
  (sort (hash-map t cons) > #:key cdr))
于 2009-07-12T18:18:48.637 回答