4

要素のリストがあります。各要素は次のように構成されています。

('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)

リストの最上位の要素を 1 つ取得することもできます。

(loop for element in list
     when (equal 'object1 (first element))
     maximize (third element))

ただし、これは 1 つの要素のみを返します。私が欲しいのは、すべての最大の要素です。collectとの組み合わせをいくつか試しましmaximizeたが、構文に関する知識はほとんどありません。「単純な」関数ですべての最高の要素を収集する方法はありますか?

4

7 に答える 7

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]

このハッシュテーブルを使用すると、現在のデータ構造よりも後の生活が楽になると思います。

于 2013-10-07T15:42:41.083 に答える
0

loop正しい最初の要素を持つすべてのサブリストを選択し、最大値を決定するためにリストを1回調べて(複数の値を蓄積intoさせるために使用できます)、次に句の2番目に選択を通過し、現在は選択のみを行うことでこれを行うことができますスコアが最大のもの:looploopfinally

(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)))

編集: または、2 番目のループの代わりに、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)))
于 2013-10-08T13:53:55.980 に答える
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)

于 2013-10-07T19:35:37.413 に答える