1

In this example, there is a list of integers '(2527 1771 2107 2317). The variable arg is an integer, which may or may not be one of the integers in the list. Q: How can an Emacs user programmatically return the next greater or lesser number than arg in the list?

Example #1: (my-func 2150 '(2527 1771 2107 2317) 'greater) => 2317

Example #2: (my-func 2150 '(2527 1771 2107 2317) 'lesser) => 2107

Example #3: (my-func 3000 '(2527 1771 2107 2317) 'greater) => nil

Example #4: (my-func 3000 '(2527 1771 2107 2317) 'lesser) => 2527

Example #5: (my-func 1000 '(2527 1771 2107 2317) 'greater) => 1771

Example #6: (my-func 1000 '(2527 1771 2107 2317) 'lesser) => nil

Example #7: (my-func 2107 '(2527 1771 2107 2317) 'greater) => 2317

Example #8: (my-func 2107 '(2527 1771 2107 2317) 'lesser) => 1771

Example #9: (my-func 2527 '(2527 1771 2107 2317) 'greater) => nil

Example #10: (my-func 2527 '(2527 1771 2107 2317) 'lesser) => 2317

Example #11: (my-func 1771 '(2527 1771 2107 2317) 'greater) => 2107

Example #12: (my-func 1771 '(2527 1771 2107 2317) 'lesser) => nil

4
  • What happens on equality?
    – NickD
    Mar 27, 2022 at 23:42
  • @NickD -- thank you ... I'll add a few examples to address equality.
    – lawlist
    Mar 28, 2022 at 0:00
  • Either you have a known sorted list (in which case you can stop looking once you cross the threshold -- but your example lists are not sorted), or else you must compare against every list item. It's simple iteration either way -- I'm sure you can write a trivial dolist solution yourself?
    – phils
    Mar 28, 2022 at 0:05
  • @phils -- thank you ... I had thought there may be a function that already does this. If not, then I will create something in the next 24 to 48 hours if there is no answer forthcoming.
    – lawlist
    Mar 28, 2022 at 0:07

2 Answers 2

3

Assuming that by lesser and greater you mean something like < and >, this seems to do what you ask.

(defun my-func (num nbs pred)
  (let (ans)
    (dolist (nb  nbs)
      (when (and (funcall pred nb num)  
                 (or (not ans)  (not (funcall pred nb ans))))
        (setq ans  nb)))
    ans))

(my-func 2150 '(2527 1771 2107 2317) #'>) ; => 2317
(my-func 2150 '(2527 1771 2107 2317) #'<) ; => 2107
(my-func 3000 '(2527 1771 2107 2317) #'>) ; => nil
(my-func 3000 '(2527 1771 2107 2317) #'<) ; => 2527
(my-func 1000 '(2527 1771 2107 2317) #'>) ; => 1771
(my-func 1000 '(2527 1771 2107 2317) #'<) ; => nil
(my-func 2107 '(2527 1771 2107 2317) #'>) ; => 2317
(my-func 2107 '(2527 1771 2107 2317) #'<) ; => 1771
(my-func 2527 '(2527 1771 2107 2317) #'>) ; => nil
(my-func 2527 '(2527 1771 2107 2317) #'<) ; => 2317
(my-func 1771 '(2527 1771 2107 2317) #'>) ; => 2107
(my-func 1771 '(2527 1771 2107 2317) #'<) ; => nil
1

Just for fun, here's a more FP-style version:

(require 'dash) ; for `-first' and `-rpartial'

(defun nearest-inequality (comparand numbers-set comparator)
  (-first
   (-rpartial comparator comparand)
   (sort numbers-set (assoc-default comparator '((< . >) (> . <))))))
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.