Generate a complete (inverserassoc
-) map assigning time-stamps to nodes at first. Afterwards sort and then locate time-stamp
in the sorted list. From there you can go forward and backward.
(defvar goto-node-timestamp-tolerance 1e-5
"Tolerance for testing equality of timestamps.")
(defun goto-node (list time-stamp n)
"Go to the desired node commencing from an existing TIME-STAMP in LIST.
If N is positive, then go forwards in time by that number of N time-stamps.
If N is negative, then backwards in time by that number of N time-stamps.
If node does not exist, return nil; otherwise, return node and corresponding time-stamp."
(let* ((full-list (apply #'append
(loop for node-stamps in list
collect (mapcar (lambda (stamp) (list (car node-stamps) stamp)) (cadr node-stamps)))))
(full-list (cl-sort full-list (lambda (node-stamp1 node-stamp2) (< (caadr node-stamp1) (caadr node-stamp2)))))
(current-pos (cl-position-if (lambda (node-stamp) (< (abs (- (caadr node-stamp) time-stamp)) goto-node-timestamp-tolerance)) full-list)))
(assert current-pos nil "Timestamp not found in list!")
(nth (max (min (+ current-pos n) (1- (length full-list))) 0) full-list)))
(setq l '(([node1] ((5.6) (3.7) (11.7) (8.2)))
([node2] ((4.4) (9.9) (6.1 . t)))
([node3] ((7.5) (2.3) (1.5)))
([node4] ((10.3)))))
(goto-node l 6.1 -1) ; => '([node3] (5.6))
(goto-node l 6.1 -4) ; => '([node3] (2.3))
(goto-node l 6.1 1) ; => '([node3] (7.5))
(goto-node l 6.1 4) ; => '([node4] (10.3))