Common Lisp - функция, которая возвращает элемент, появляется n раз в списке - PullRequest
1 голос
/ 19 апреля 2020

Я пытаюсь написать функцию, которая возвращает элемент, появляется n раз в списке.

Например, для списка, подобного: (setq lst '(a b b b c)), функция возвращает:

count-list (lst 3) --> b

Но когда есть два элемента (или более), которые появляются в n раз, функция возвращает только первый элемент:

count-list (lst 1) --> a

Вместо

count-list (lst 1) --> a b

Вот функция:

(defun count-list (lst nb)
    (loop for x in lst do
        (if (eq (count x lst) nb)
            (return x)
            )
        )
    )

Что я пропустил?

Ответы [ 2 ]

2 голосов
/ 19 апреля 2020

return сообщает функции count-list о немедленном выходе, как только она обнаружит попадание, поэтому она не будет искать другие элементы, соответствующие количеству. Одно из возможных решений заключается в следующем:

(defun count-list (lst n) 
  (remove-duplicates 
    (mapcan #'(lambda (x) 
                (when (eql (count x lst) n) 
                  (list x) )) 
         lst )))

Однако это очень неэффективно, поскольку для каждого элемента список необходимо пересматривать дважды, один для самой функции и один для счетчика, так что это займет время, пропорциональное до квадрата длины списка.
Более эффективным способом было бы накапливать значения (например, в ассо c списке) и выбирать в конце те элементы, которые соответствуют числу входных счетчиков.

  (defun count-list (lst n)
    (let* (count-list pair)
      (dolist (x lst)
        (if (setq pair (assoc x count-list))
          (incf (cdr pair))
          (push (cons x 1) count-list) ))
      (mapcan #'(lambda (pair) 
                  (when (eql n (cdr pair))
                     (list (car pair)) )) 
              count-list )))
0 голосов
/ 19 апреля 2020

Я никогда не использовал LISP. Я предполагаю, что ваша проблема в том, что ваша функция возвращается при первом совпадении. Либо создайте в вашей функции массив для хранения всех элементов, появляющихся n раз, и вернитесь к этому массиву, либо, например, в Python я бы использовал print(x), чтобы функция не возвращалась при первом совпадении, как в вашем случай.

...