560 lines
No EOL
13 KiB
HTML
560 lines
No EOL
13 KiB
HTML
<!DOCTYPE HTML>
|
|
<HTML LANG="en-us"
|
|
><HEAD
|
|
><TITLE
|
|
>sort, stable-sort | Common Lisp Nova Spec</TITLE
|
|
><META CHARSET="US-ASCII"
|
|
><LINK REL="canonical" HREF="f_sort.html"
|
|
><LINK REL="next" HREF="f_find.html" TYPE="text/html" TITLE="find, find-if, find-if-not"
|
|
><LINK REL="prev" HREF="f_reverse.html" TYPE="text/html" TITLE="reverse, nreverse"
|
|
><LINK REL="up" HREF="17_3_Sequences_Dictionary.html" TYPE="text/html" TITLE="17.3 Sequences Dictionary"
|
|
><LINK REL="start" HREF="index.html" TYPE="text/html" TITLE="Common Lisp Nova Spec"
|
|
><META NAME="VIEWPORT" CONTENT="width=device-width, initial-scale=1.0"
|
|
><LINK REL="STYLESHEET" HREF="dpans.css%3F3909942064.css"
|
|
><SCRIPT SRC="dpans.js%3F3909942064"
|
|
></SCRIPT
|
|
><SCRIPT SRC="apropos.js%3F3909942064"
|
|
></SCRIPT
|
|
></HEAD
|
|
><BODY
|
|
><DIV
|
|
><DIV CLASS="topnav"
|
|
><DIV CLASS="breadcrumb"
|
|
><SPAN CLASS="breadcrumb-item"
|
|
><A HREF="index.html"
|
|
>Common Lisp Nova Spec</A
|
|
></SPAN
|
|
> <SPAN CLASS="breadcrumb-item"
|
|
>→ <A HREF="17_Sequences.html"
|
|
>17. Sequences</A
|
|
></SPAN
|
|
> <SPAN CLASS="breadcrumb-item"
|
|
>→ <A HREF="17_3_Sequences_Dictionary.html"
|
|
>17.3 Sequences Dictionary</A
|
|
></SPAN
|
|
> <SPAN CLASS="breadcrumb-item"
|
|
>→ <A HREF="f_sort.html"
|
|
>sort, stable-sort</A
|
|
></SPAN
|
|
></DIV
|
|
><DIV CLASS="apropos"
|
|
><DIV CLASS="apropos-io"
|
|
><A HREF="f_reverse.html" CLASS="prev"
|
|
>←</A
|
|
><SPAN ID="apropos-label"
|
|
>Apropos </SPAN
|
|
><INPUT ID="apropos" AUTOFOCUS="AUTOFOCUS" PLACEHOLDER="Type here to search" ONINPUT="aproposInput(this);" ONKEYUP="aproposKeyup(event);" ONCHANGE="aproposChange(this);" ONFOCUS="aproposFocus(this);" ONFOCUSOUT="aproposFocusout(this);"
|
|
><A HREF="f_find.html" CLASS="next"
|
|
>→</A
|
|
></DIV
|
|
><DIV ID="apropos-res"
|
|
></DIV
|
|
></DIV
|
|
></DIV
|
|
><DIV CLASS="matter"
|
|
><DIV CLASS="com"
|
|
><DIV CLASS="begincom"
|
|
><HR
|
|
><TABLE WIDTH="100%" CELLSPACING="0" CELLPADDING="0"
|
|
><TR
|
|
><TD ALIGN="LEFT" VALIGN="BASELINE" WIDTH="100%" CLASS="name"
|
|
><SPAN CLASS="idx" DATA-KIND="idxref" DATA-TERM="sort, stable-sort"
|
|
></SPAN
|
|
><B
|
|
>sort, stable-sort</B
|
|
></TD
|
|
><TD ALIGN="RIGHT" VALIGN="BASELINE" WIDTH="0" NOWRAP="NOWRAP" CLASS="ftype"
|
|
><I
|
|
>Function</I
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
></DIV
|
|
><UL CLASS="subtoc"
|
|
></UL
|
|
><DL
|
|
><DT
|
|
><B
|
|
>Syntax</B
|
|
></DT
|
|
><DD
|
|
><P CLASS="j"
|
|
><B
|
|
>sort</B
|
|
> <SPAN CLASS="cmssi"
|
|
>sequence</SPAN
|
|
> <SPAN CLASS="cmssi"
|
|
>predicate</SPAN
|
|
> <SPAN CLASS="cmtt"
|
|
>&key</SPAN
|
|
> <SPAN CLASS="cmssi"
|
|
>key</SPAN
|
|
> <SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
> <SPAN CLASS="cmssi"
|
|
>sorted-sequence</SPAN
|
|
></P
|
|
><P CLASS="j"
|
|
><B
|
|
>stable-sort</B
|
|
> <SPAN CLASS="cmssi"
|
|
>sequence</SPAN
|
|
> <SPAN CLASS="cmssi"
|
|
>predicate</SPAN
|
|
> <SPAN CLASS="cmtt"
|
|
>&key</SPAN
|
|
> <SPAN CLASS="cmssi"
|
|
>key</SPAN
|
|
> <SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
> <SPAN CLASS="cmssi"
|
|
>sorted-sequence</SPAN
|
|
></P
|
|
></DD
|
|
><DT
|
|
><B
|
|
>Arguments and Values</B
|
|
></DT
|
|
><DD
|
|
><P CLASS="j"
|
|
><VAR CLASS="param"
|
|
>sequence</VAR
|
|
> — a <A HREF="26_1_Glossary.html#proper_sequence"
|
|
><EM CLASS="term"
|
|
>proper sequence</EM
|
|
></A
|
|
>. </P
|
|
><P CLASS="j"
|
|
><VAR CLASS="param"
|
|
>predicate</VAR
|
|
> — a <A HREF="26_1_Glossary.html#designator"
|
|
><EM CLASS="term"
|
|
>designator</EM
|
|
></A
|
|
> for a <A HREF="26_1_Glossary.html#function"
|
|
><EM CLASS="term"
|
|
>function</EM
|
|
></A
|
|
> of two arguments that returns a <A HREF="26_1_Glossary.html#generalized_boolean"
|
|
><EM CLASS="term"
|
|
>generalized boolean</EM
|
|
></A
|
|
>. </P
|
|
><P CLASS="j"
|
|
><VAR CLASS="param"
|
|
>key</VAR
|
|
> — a <A HREF="26_1_Glossary.html#designator"
|
|
><EM CLASS="term"
|
|
>designator</EM
|
|
></A
|
|
> for a <A HREF="26_1_Glossary.html#function"
|
|
><EM CLASS="term"
|
|
>function</EM
|
|
></A
|
|
> of one argument, or <SPAN CLASS="misc"
|
|
><B
|
|
>nil</B
|
|
></SPAN
|
|
>. </P
|
|
><P CLASS="j"
|
|
><VAR CLASS="param"
|
|
>sorted-sequence</VAR
|
|
> — a <A HREF="26_1_Glossary.html#sequence"
|
|
><EM CLASS="term"
|
|
>sequence</EM
|
|
></A
|
|
>.</P
|
|
></DD
|
|
><DT
|
|
><B
|
|
>Description</B
|
|
></DT
|
|
><DD
|
|
><P CLASS="j"
|
|
><A HREF="f_sort.html" CLASS="funref"
|
|
><B
|
|
>sort</B
|
|
></A
|
|
> and <A HREF="f_sort.html" CLASS="funref"
|
|
><B
|
|
>stable-sort</B
|
|
></A
|
|
> destructively sort <VAR CLASS="param"
|
|
>sequences</VAR
|
|
> according to the order determined by the <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> function. </P
|
|
><P CLASS="j"
|
|
>If <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> is a <A HREF="26_1_Glossary.html#vector"
|
|
><EM CLASS="term"
|
|
>vector</EM
|
|
></A
|
|
>, the result is a <A HREF="26_1_Glossary.html#vector"
|
|
><EM CLASS="term"
|
|
>vector</EM
|
|
></A
|
|
> that has the same <A HREF="26_1_Glossary.html#actual_array_element_type"
|
|
><EM CLASS="term"
|
|
>actual array element type</EM
|
|
></A
|
|
> as <VAR CLASS="param"
|
|
>sequence</VAR
|
|
>. If <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> is a <A HREF="26_1_Glossary.html#list"
|
|
><EM CLASS="term"
|
|
>list</EM
|
|
></A
|
|
>, the result is a <A HREF="26_1_Glossary.html#list"
|
|
><EM CLASS="term"
|
|
>list</EM
|
|
></A
|
|
>. </P
|
|
><P CLASS="j"
|
|
><A HREF="f_sort.html" CLASS="funref"
|
|
><B
|
|
>sort</B
|
|
></A
|
|
> determines the relationship between two elements by giving keys extracted from the elements to the <VAR CLASS="param"
|
|
>predicate</VAR
|
|
>. The first argument to the <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> function is the part of one element of <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> extracted by the <VAR CLASS="param"
|
|
>key</VAR
|
|
> function (if supplied); the second argument is the part of another element of <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> extracted by the <VAR CLASS="param"
|
|
>key</VAR
|
|
> function (if supplied). <VAR CLASS="param"
|
|
>Predicate</VAR
|
|
> should return <A HREF="26_1_Glossary.html#true"
|
|
><EM CLASS="term"
|
|
>true</EM
|
|
></A
|
|
> if and only if the first argument is strictly less than the second (in some appropriate sense). If the first argument is greater than or equal to the second (in the appropriate sense), then the <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> should return <A HREF="26_1_Glossary.html#false"
|
|
><EM CLASS="term"
|
|
>false</EM
|
|
></A
|
|
>. </P
|
|
><P CLASS="j"
|
|
>The argument to the <VAR CLASS="param"
|
|
>key</VAR
|
|
> function is the <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> element. The return value of the <VAR CLASS="param"
|
|
>key</VAR
|
|
> function becomes an argument to <VAR CLASS="param"
|
|
>predicate</VAR
|
|
>. If <VAR CLASS="param"
|
|
>key</VAR
|
|
> is not supplied or <SPAN CLASS="misc"
|
|
><B
|
|
>nil</B
|
|
></SPAN
|
|
>, the <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> element itself is used. There is no guarantee on the number of times the <VAR CLASS="param"
|
|
>key</VAR
|
|
> will be called. </P
|
|
><P CLASS="j"
|
|
>If the <VAR CLASS="param"
|
|
>key</VAR
|
|
> and <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> always return, then the sorting operation will always terminate, producing a <A HREF="26_1_Glossary.html#sequence"
|
|
><EM CLASS="term"
|
|
>sequence</EM
|
|
></A
|
|
> containing the same <A HREF="26_1_Glossary.html#element"
|
|
><EM CLASS="term"
|
|
>elements</EM
|
|
></A
|
|
> as <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> (that is, the result is a permutation of <VAR CLASS="param"
|
|
>sequence</VAR
|
|
>). This is guaranteed even if the <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> does not really consistently represent a total order (in which case the <A HREF="26_1_Glossary.html#element"
|
|
><EM CLASS="term"
|
|
>elements</EM
|
|
></A
|
|
> will be scrambled in some unpredictable way, but no <A HREF="26_1_Glossary.html#element"
|
|
><EM CLASS="term"
|
|
>element</EM
|
|
></A
|
|
> will be lost). If the <VAR CLASS="param"
|
|
>key</VAR
|
|
> consistently returns meaningful keys, and the <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> does reflect some total ordering criterion on those keys, then the <A HREF="26_1_Glossary.html#element"
|
|
><EM CLASS="term"
|
|
>elements</EM
|
|
></A
|
|
> of the <VAR CLASS="param"
|
|
>sorted-sequence</VAR
|
|
> will be properly sorted according to that ordering. </P
|
|
><P CLASS="j"
|
|
>The sorting operation performed by <A HREF="f_sort.html" CLASS="funref"
|
|
><B
|
|
>sort</B
|
|
></A
|
|
> is not guaranteed stable. Elements considered equal by the <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> might or might not stay in their original order. The <VAR CLASS="param"
|
|
>predicate</VAR
|
|
> is assumed to consider two elements <CODE CLASS="f"
|
|
>x</CODE
|
|
> and <CODE CLASS="f"
|
|
>y</CODE
|
|
> to be equal if <CODE CLASS="f"
|
|
>(funcall <I CLASS="i"
|
|
><I
|
|
>predicate</I
|
|
></I
|
|
> <I CLASS="i"
|
|
><I
|
|
>x</I
|
|
></I
|
|
> <I CLASS="i"
|
|
><I
|
|
>y</I
|
|
></I
|
|
>)</CODE
|
|
> and <CODE CLASS="f"
|
|
>(funcall <I CLASS="i"
|
|
><I
|
|
>predicate</I
|
|
></I
|
|
> <I CLASS="i"
|
|
><I
|
|
>y</I
|
|
></I
|
|
> <I CLASS="i"
|
|
><I
|
|
>x</I
|
|
></I
|
|
>)</CODE
|
|
> are both <A HREF="26_1_Glossary.html#false"
|
|
><EM CLASS="term"
|
|
>false</EM
|
|
></A
|
|
>. <A HREF="f_sort.html" CLASS="funref"
|
|
><B
|
|
>stable-sort</B
|
|
></A
|
|
> guarantees stability. </P
|
|
><P CLASS="j"
|
|
>The sorting operation can be destructive in all cases. In the case of a <A HREF="26_1_Glossary.html#vector"
|
|
><EM CLASS="term"
|
|
>vector</EM
|
|
></A
|
|
> argument, this is accomplished by permuting the elements in place. In the case of a <A HREF="26_1_Glossary.html#list"
|
|
><EM CLASS="term"
|
|
>list</EM
|
|
></A
|
|
>, the <A HREF="26_1_Glossary.html#list"
|
|
><EM CLASS="term"
|
|
>list</EM
|
|
></A
|
|
> is destructively reordered in the same manner as for <A HREF="f_reverse.html" CLASS="funref"
|
|
><B
|
|
>nreverse</B
|
|
></A
|
|
>.</P
|
|
></DD
|
|
><DT
|
|
><B
|
|
>Examples</B
|
|
></DT
|
|
><DD
|
|
><PRE CLASS="screen"
|
|
> (setq tester (copy-seq "lkjashd")) <SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> "lkjashd"
|
|
(sort tester #'char-lessp) <SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> "adhjkls"
|
|
(setq tester (list '(1 2 3) '(4 5 6) '(7 8 9))) <SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> ((1 2 3) (4 5 6) (7 8 9))
|
|
(sort tester #'> :key #'car) <SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> ((7 8 9) (4 5 6) (1 2 3))
|
|
(setq tester (list 1 2 3 4 5 6 7 8 9 0)) <SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> (1 2 3 4 5 6 7 8 9 0)
|
|
(stable-sort tester #'(lambda (x y) (and (oddp x) (evenp y))))
|
|
<SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> (1 3 5 7 9 2 4 6 8 0)
|
|
(sort (setq committee-data
|
|
(vector (list (list "JonL" "White") "Iteration")
|
|
(list (list "Dick" "Waters") "Iteration")
|
|
(list (list "Dick" "Gabriel") "Objects")
|
|
(list (list "Kent" "Pitman") "Conditions")
|
|
(list (list "Gregor" "Kiczales") "Objects")
|
|
(list (list "David" "Moon") "Objects")
|
|
(list (list "Kathy" "Chapman") "Editorial")
|
|
(list (list "Larry" "Masinter") "Cleanup")
|
|
(list (list "Sandra" "Loosemore") "Compiler")))
|
|
#'string-lessp :key #'cadar)
|
|
<SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> #((("Kathy" "Chapman") "Editorial")
|
|
(("Dick" "Gabriel") "Objects")
|
|
(("Gregor" "Kiczales") "Objects")
|
|
(("Sandra" "Loosemore") "Compiler")
|
|
(("Larry" "Masinter") "Cleanup")
|
|
(("David" "Moon") "Objects")
|
|
(("Kent" "Pitman") "Conditions")
|
|
(("Dick" "Waters") "Iteration")
|
|
(("JonL" "White") "Iteration"))
|
|
;; Note that individual alphabetical order within `committees'
|
|
;; is preserved.
|
|
(setq committee-data
|
|
(stable-sort committee-data #'string-lessp :key #'cadr))
|
|
<SPAN CLASS="cmsy"
|
|
><SPAN CLASS="arrow"
|
|
>→</SPAN
|
|
></SPAN
|
|
> #((("Larry" "Masinter") "Cleanup")
|
|
(("Sandra" "Loosemore") "Compiler")
|
|
(("Kent" "Pitman") "Conditions")
|
|
(("Kathy" "Chapman") "Editorial")
|
|
(("Dick" "Waters") "Iteration")
|
|
(("JonL" "White") "Iteration")
|
|
(("Dick" "Gabriel") "Objects")
|
|
(("Gregor" "Kiczales") "Objects")
|
|
(("David" "Moon") "Objects"))</PRE
|
|
></DD
|
|
><DT
|
|
><B
|
|
>Exceptional Situations</B
|
|
></DT
|
|
><DD
|
|
><P CLASS="j"
|
|
>Should be prepared to signal an error of <A HREF="26_1_Glossary.html#type"
|
|
><EM CLASS="term"
|
|
>type</EM
|
|
></A
|
|
> <A HREF="t_type-error.html" CLASS="typeref"
|
|
><B
|
|
>type-error</B
|
|
></A
|
|
> if <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> is not a <A HREF="26_1_Glossary.html#proper_sequence"
|
|
><EM CLASS="term"
|
|
>proper sequence</EM
|
|
></A
|
|
>.</P
|
|
></DD
|
|
><DT
|
|
><B
|
|
>See Also</B
|
|
></DT
|
|
><DD
|
|
><P CLASS="j"
|
|
><A HREF="f_merge.html" CLASS="funref"
|
|
><B
|
|
>merge</B
|
|
></A
|
|
>, <A HREF="3_2_Compilation.html#sec_3_2_1" CLASS="secref"
|
|
><SPAN CLASS="cmr"
|
|
>Section</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>3.2.1</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>(Compiler</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>Terminology)</SPAN
|
|
></A
|
|
>, <A HREF="3_6_Traversal_Rules_and_Side_Effects.html#sec_3_6" CLASS="secref"
|
|
><SPAN CLASS="cmr"
|
|
>Section</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>3.6</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>(Traversal</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>Rules</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>and</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>Side</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>Effects)</SPAN
|
|
></A
|
|
>, <A HREF="3_7_Destructive_Operations.html#sec_3_7" CLASS="secref"
|
|
><SPAN CLASS="cmr"
|
|
>Section</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>3.7</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>(Destructive</SPAN
|
|
> <SPAN CLASS="cmr"
|
|
>Operations)</SPAN
|
|
></A
|
|
></P
|
|
></DD
|
|
><DT
|
|
><B
|
|
>Notes</B
|
|
></DT
|
|
><DD
|
|
><P CLASS="j"
|
|
>If <VAR CLASS="param"
|
|
>sequence</VAR
|
|
> is a <A HREF="26_1_Glossary.html#vector"
|
|
><EM CLASS="term"
|
|
>vector</EM
|
|
></A
|
|
>, the result might or might not be simple, and might or might not be <A HREF="26_1_Glossary.html#identical"
|
|
><EM CLASS="term"
|
|
>identical</EM
|
|
></A
|
|
> to <VAR CLASS="param"
|
|
>sequence</VAR
|
|
>.</P
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
></DIV
|
|
><DIV CLASS="footer"
|
|
><DIV CLASS="btmnav"
|
|
><A HREF="f_reverse.html" CLASS="prev"
|
|
>←</A
|
|
><A HREF="f_find.html" CLASS="next"
|
|
>→</A
|
|
></DIV
|
|
><DIV CLASS="trail"
|
|
>Conversion to HTML copyright 2023 by Gilbert Baumann</DIV
|
|
></DIV
|
|
></DIV
|
|
><SCRIPT
|
|
>domReady();</SCRIPT
|
|
></BODY
|
|
></HTML
|
|
> |