From 27c5eac34b5950c147bdb3e04cb87f5feca4c471 Mon Sep 17 00:00:00 2001 From: Zhu Zihao Date: Fri, 17 Mar 2023 00:27:52 +0800 Subject: [PATCH] Add -shuffle * dash.el (-shuffle): New function. * dev/examples.el (-shuffle): New example. * README.md: * dash.texi: Regenerate docs. --- README.md | 24 ++++++++++++++++++++++++ dash.el | 14 ++++++++++++++ dash.texi | 23 +++++++++++++++++++++++ dev/examples.el | 12 ++++++++++++ 4 files changed, 73 insertions(+) diff --git a/README.md b/README.md index b3591771..992bb9a4 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,7 @@ Other list functions not fit to be classified elsewhere. * [`-butlast`](#-butlast-list) `(list)` * [`-sort`](#-sort-comparator-list) `(comparator list)` * [`-to-head`](#-to-head-n-list) `(n list)` +* [`-shuffle`](#-shuffle-list) `(list)` * [`-list`](#-list-arg) `(arg)` * [`-fix`](#-fix-fn-list) `(fn list)` @@ -2318,6 +2319,29 @@ if the first element should sort before the second. (--sort (< it other) '(3 1 2)) ;; => (1 2 3) ``` +#### -to-head `(n list)` + +Return a new list that move the element at `n`th to the head of old `list`. + +```el +(-to-head 3 '(1 2 3 4 5)) ;; => (4 1 2 3 5) +(-to-head 5 '(1 2 3 4 5)) ;; peculiar error +(let ((l '(1 2 3 4 5))) (list (-to-head 2 l) l)) ;; => ((3 1 2 4 5) (1 2 3 4 5)) +``` + +#### -shuffle `(list)` + +Return a new shuffled `list`. + +The returned list is shuffled by using Fisher-Yates' Algorithm. See +https://en.wikipedia.org/wiki/Fisher-Yates_shuffle for more details. + +```el +(progn (random "dash1") (-shuffle '(1 2 3 4 5 6 7))) ;; => (2 7 6 4 5 1 3) +(progn (random "dash2") (-shuffle '(1 2 3 4 5 6 7))) ;; => (1 5 2 4 3 7 6) +(let ((l '(1 2 3 4 5 6 7))) (random "dash3") (list (-shuffle '(1 2 3 4 5 6 7)) l)) ;; => ((3 4 1 5 7 6 2) (1 2 3 4 5 6 7)) +``` + #### -list `(arg)` Ensure `arg` is a list. diff --git a/dash.el b/dash.el index 433a12f7..17a3f1ee 100644 --- a/dash.el +++ b/dash.el @@ -3248,6 +3248,20 @@ if the first element should sort before the second." (target (pop rest))) (cons target (nconc head rest)))) +(defun -shuffle (list) + "Return a new shuffled LIST. + +The returned list is shuffled by using Fisher-Yates' Algorithm. See +https://en.wikipedia.org/wiki/Fisher-Yates_shuffle for more details." + (declare (pure t) (side-effect-free t)) + (let* ((len (length list)) + (random-nums (-map #'random (number-sequence len 1 -1))) + result) + (--each random-nums + (setq list (-to-head it list)) + (push (pop list) result)) + (nreverse result))) + (defun -list (&optional arg &rest args) "Ensure ARG is a list. If ARG is already a list, return it as is (not a copy). diff --git a/dash.texi b/dash.texi index da96033c..f2566806 100644 --- a/dash.texi +++ b/dash.texi @@ -3498,6 +3498,29 @@ Return a new list that move the element at Nth to the head of old @var{list}. @end example @end defun +@anchor{-shuffle} +@defun -shuffle (list) +Return a new shuffled @var{list}. + +The returned list is shuffled by using Fisher-Yates' Algorithm. See +https://en.wikipedia.org/wiki/Fisher-Yates_shuffle for more details. + +@example +@group +(progn (random "dash1") (-shuffle '(1 2 3 4 5 6 7))) + @result{} (2 7 6 4 5 1 3) +@end group +@group +(progn (random "dash2") (-shuffle '(1 2 3 4 5 6 7))) + @result{} (1 5 2 4 3 7 6) +@end group +@group +(let ((l '(1 2 3 4 5 6 7))) (random "dash3") (list (-shuffle '(1 2 3 4 5 6 7)) l)) + @result{} ((3 4 1 5 7 6 2) (1 2 3 4 5 6 7)) +@end group +@end example +@end defun + @anchor{-list} @defun -list (arg) Ensure @var{arg} is a list. diff --git a/dev/examples.el b/dev/examples.el index a5157e59..feeea867 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -1927,6 +1927,18 @@ related predicates." (let ((l '(1 2 3 4 5))) (list (-to-head 2 l) l)) => '((3 1 2 4 5) (1 2 3 4 5))) + (defexamples -shuffle + (progn + (random "dash1") + (-shuffle '(1 2 3 4 5 6 7))) => '(2 7 6 4 5 1 3) + (progn + (random "dash2") + (-shuffle '(1 2 3 4 5 6 7))) => '(1 5 2 4 3 7 6) + (let ((l '(1 2 3 4 5 6 7))) + (random "dash3") + (list (-shuffle '(1 2 3 4 5 6 7)) l)) => '((3 4 1 5 7 6 2) (1 2 3 4 5 6 7)) + (-shuffle nil) => nil) + (defexamples -list (-list 1) => '(1) (-list '()) => '()