In the following example, there are two criteria for sorting -- orders with an inactive status should appear last in the last, and all orders should be organized by order number from smallest to largest. The problem with the current approach is that the orders with an inactive status are not being sorted by their order numbers. How can a user programmatically specify the order in which sorts are performed? E.g., first sort by status, and then sort everything by number; or, first sort everything by number, and then sort by status without altering the initial sort.
(let ((seq '((5996635507 (((rank . parent) (status . "CANCELED")) (misc ."misc")))
(5996635504 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc ."misc")))
(5996635414 (((rank . child) (status . "AWAITING_PARENT_ORDER")) (misc ."misc")))
(5996635416 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc ."misc")))
(5996635415 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc ."misc")))
(5996635413 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc ."misc")))
(5996635115 (((rank . parent) (status . "CANCELED")) (misc ."misc")))))
(inactive-list '("REJECTED" "CANCELED" "REPLACED" "FILLED" "EXPIRED")))
(sort seq (lambda (a b)
(let* ((order-number-a (car a))
(order-number-b (car b))
(alist-a (caadr a))
(alist-b (caadr b))
(status-a (cdr (assq 'status alist-a)))
(status-b (cdr (assq 'status alist-b))))
(and (< order-number-a order-number-b)
(not (member status-a inactive-list)))))))
CURRENT RESULT: Order 5996635507
is before order 5996635115
.
((5996635413 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc . "misc")))
(5996635414 (((rank . child) (status . "AWAITING_PARENT_ORDER")) (misc . "misc")))
(5996635415 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc . "misc")))
(5996635416 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc . "misc")))
(5996635504 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc . "misc")))
(5996635507 (((rank . parent) (status . "CANCELED")) (misc . "misc")))
(5996635115 (((rank . parent) (status . "CANCELED")) (misc . "misc"))))
DESIRED RESULT: Order 5996635507
is after order 5996635115
.
((5996635413 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc . "misc")))
(5996635414 (((rank . child) (status . "AWAITING_PARENT_ORDER")) (misc . "misc")))
(5996635415 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc . "misc")))
(5996635416 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc . "misc")))
(5996635504 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc . "misc")))
(5996635115 (((rank . parent) (status . "CANCELED")) (misc . "misc")))
(5996635507 (((rank . parent) (status . "CANCELED")) (misc . "misc"))))
SECOND ATTEMPT:
(let ((seq '((5996635507 (((rank . parent) (status . "CANCELED")) (misc ."misc")))
(5996635504 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc ."misc")))
(5996635414 (((rank . child) (status . "AWAITING_PARENT_ORDER")) (misc ."misc")))
(5996635416 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc ."misc")))
(5996635415 (((rank . grandchild) (status . "AWAITING_PARENT_ORDER")) (misc ."misc")))
(5996635413 (((rank . parent) (status . "PENDING_ACTIVATION")) (misc ."misc")))
(5996635115 (((rank . parent) (status . "CANCELED")) (misc ."misc")))))
(inactive-list '("REJECTED" "CANCELED" "REPLACED" "FILLED" "EXPIRED")))
(sort seq (lambda (a b)
(let* ((order-number-a (car a))
(order-number-b (car b))
(alist-a (caadr a))
(alist-b (caadr b))
(status-a (cdr (assq 'status alist-a)))
(status-b (cdr (assq 'status alist-b))))
(cond
((and (not (member status-a inactive-list))
(not (member status-b inactive-list)))
(< order-number-a order-number-b))
((and (member status-a inactive-list)
(member status-b inactive-list))
(< order-number-a order-number-b))
((and (member status-a inactive-list)
(not (member status-b inactive-list)))
nil)
((and (not (member status-a inactive-list))
(member status-b inactive-list))
t))))))