我有一个元素列表。每个元素的结构如下:
('symbol "string" int-score)
示例列表:
(list (list 'object1 "wabadu" 0.5)
(list 'object2 "xezulu" 0.6)
(list 'object1 "yebasi" 0.5)
(list 'object1 "tesora" 0.2))
我想检索特定符号的最大值。当我用符号object2
搜索时,我应该回来:
('object2 "xezulu" 0.6)
如果我使用object1
进行搜索,我应该回来:
(('object1 "wabadu" 0.5) ('object1 "yebasi" 0.5))
我想收集特定对象的所有最高元素。我能做的是:假设上面的列表是下面使用的列表,我正在搜索object1
。我可以检索特定对象的所有元素:
(loop for element in list
when (equal 'object1 (first element))
collect element)
我还可以检索列表中的一个最高元素:
(loop for element in list
when (equal 'object1 (first element))
maximize (third element))
但是,这只会返回一个元素。我想要的是所有最大元素。我尝试过使用collect
和maximize
的一些组合,但我对语法的了解很少。有没有办法收集“简单”功能中的所有最高元素?
答案 0 :(得分:2)
基于LOOP版本的草图:
(defun mymax (target list &aux result max)
(loop for (item name value) in list
when (eql item target)
do (cond ((or (null result)
(> value max))
(setf result (list (list item name value))
max value))
((= value max)
(push (list item name value) result))))
result)
答案 1 :(得分:1)
这将创建一个hash-table
,其中键是符号,值的排列方式为(maximum . (list of strings corresponding to maximum))
(let ((data (list (list 'object1 "wabadu" 0.5)
(list 'object2 "xezulu" 0.6)
(list 'object1 "yebasi" 0.5)
(list 'object1 "tesora" 0.2))))
(loop
:with table := (make-hash-table)
:for (item string num) :in data :do
(destructuring-bind (&optional max strings)
(gethash item table)
(cond
((or (null max) (< max num))
(setf (gethash item table) (list num (list string))))
((= max num)
(setf (cdr strings) (cons string (cdr strings))))))
:finally (return table)))
;; #<HASH-TABLE {1005C6BE93}>
;; --------------------
;; Count: 2
;; Size: 16
;; Test: EQL
;; Rehash size: 1.5
;; Rehash threshold: 1.0
;; [clear hashtable]
;; Contents:
;; OBJECT1 = (0.5 ("wabadu" "yebasi")) [remove entry]
;; OBJECT2 = (0.6 ("xezulu")) [remove entry]
我认为使用此哈希表然后使用您当前拥有的数据结构,您的生活将更加轻松。
答案 2 :(得分:0)
maximize
只返回一个元素。您可以按第3个组件对所有列表进行排序,然后获取前面的组件。像这样:
;;; suppose a copy of the data is stored in l
;; get all 'object1 and sort them
(setf l (sort (remove-if-not
(lambda (x) (equal (first x) 'object1)) l)
#'> :key #'third))
;; remove the ones with smaller value than the first one
(setf l (remove-if
(lambda (x) (< (third x) (third (first l)))) l))
答案 3 :(得分:0)
提取您的数据以创建基本构建块;将构建块组合到您所需的功能中:
(defun make-foo (type name score)
(list type name score))
(defun foo-type (foo) (elt foo 0))
;; ...
(defun make-foos (&rest foos)
foos)
(defun foos-find-if (foos predicate)
;; return all foos satisfying predicate
)
(defun foos-maximize (foos orderer)
;; return the maximum foo (any one)
)
(defun foos-find-if-maximized (foos)
(foos-find-if foos
(let ((max (foos-maximize foos #'foo-score)))
(lambda (foo)
(= (foo-score max) (foo-score foo))))))
答案 4 :(得分:0)
这是一种方法,首先保存只包含搜索对象列表的symbol-list
。然后我们可以轻松获得最大值并删除那些值较小的列表。
(defun foo (symbol list)
(let* ((symbol-list (remove-if-not #'(lambda (l) (eq (first l) symbol))
list))
(max (apply #'max (mapcar #'third symbol-list))))
(remove-if-not #'(lambda (l) (= (third l) max))
symbol-list)))
我们可以称之为:(foo 'object1 l)
答案 5 :(得分:0)
您可以loop
在列表中执行此操作,以选择具有正确第一个元素的所有子列表并确定最大值(您可以使用into
让loop
累积多个值),然后loop
子句中的第二个finally
进行选择,现在只选择那些得分最高的那些:
(loop for triple in *l*
for (key nil score) = triple
when (eq key 'object1)
collect triple into selection
and maximize score into max-score
finally (return (loop for triple in selection
when (eql (third triple) max-score)
collect triple)))
编辑:或者,代替第二个循环,可以非常简洁地使用delete
函数:
(loop for triple in *l*
for (key name score) = triple
when (eq key 'object1)
collect triple into selection
and maximize score into max-score
finally (return (delete max-score selection
:test #'/=
:key #'third)))
答案 6 :(得分:0)
根据经验,如果你真的想将一系列事物简化为一个结果,那么应该有一个很好的方法来实现这一点。
还有:
(defun collect-maxima-by-third (list)
(reduce
#'(lambda (max-list next-element)
(let ((max-value (third (first max-list)))
(next-value (third next-element)))
(cond ((< max-value next-value)
(list next-element))
((= max-value next-value)
(cons next-element max-list))
(t max-list)))) ; the greater-than case
(rest list)
:initial-value (list (first list))))
它并不完美,就好像你给它一个空列表一样,它会给你一个包含空列表的列表,而不仅仅是一个空列表,但如果你认为这种情况经常发生,你可以轻松地为此添加一个案例。 / p>
这种技术(可能不是这个确切的例子)详细介绍了函数式编程的各种文本;一些Haskell文本做得特别好(想想你是一个Haskell)。