Sort using a custom comparator: Difference between revisions

m
m (Added output)
m (→‎{{header|Wren}}: Minor tidy)
 
(29 intermediate revisions by 20 users not shown)
Line 1:
{{task|Sorting Algorithms}}
[[Category:Sorting]]
{{Sorting Algorithm}}
{{task|Sorting Algorithms}}
{{omit from|BBC BASIC}}
 
Line 15:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">V strings = ‘here are Some sample strings to be sorted’.split(‘ ’)
 
print(sorted(strings, key' x -> (-x.len, x.uppercase())))</langsyntaxhighlight>
 
{{out}}
Line 26:
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits}}
<syntaxhighlight lang="aarch64 assembly">
<lang AArch64 Assembly>
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program customSort64.s */
Line 384:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
</lang>
<pre>
Name : London country : UK
Line 408:
Name : Birmingham country : UK
Name : Birmingham country : US
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
 
PROC PrintArray(PTR ARRAY a INT size)
INT i
 
Put('[)
FOR i=0 TO size-1
DO
IF i>0 THEN Put(' ) FI
Print(a(i))
OD
Put(']) PutE()
RETURN
 
INT FUNC CustomComparator(CHAR ARRAY s1,s2)
INT res
 
res=s2(0) res==-s1(0)
IF res=0 THEN
res=SCompare(s1,s2)
FI
RETURN (res)
 
INT FUNC Comparator=*(CHAR ARRAY s1,s2)
DEFINE JSR="$20"
DEFINE RTS="$60"
[JSR $00 $00 ;JSR to address set by SetComparator
RTS]
 
PROC SetComparator(PTR p)
PTR addr
 
addr=Comparator+1 ;location of address of JSR
PokeC(addr,p)
RETURN
 
PROC InsertionSort(PTR ARRAY a INT size PTR compareFun)
INT i,j
CHAR ARRAY s
 
SetComparator(compareFun)
FOR i=1 TO size-1
DO
s=a(i)
j=i-1
WHILE j>=0 AND Comparator(s,a(j))<0
DO
a(j+1)=a(j)
j==-1
OD
a(j+1)=s
OD
RETURN
 
PROC Test(PTR ARRAY a INT size PTR compareFun)
PrintE("Array before sort:")
PrintArray(a,size)
PutE()
 
InsertionSort(a,size,compareFun)
PrintE("Array after sort:")
PrintArray(a,size)
PutE()
RETURN
 
PROC Main()
PTR ARRAY a(24)
 
a(0)="lorem" a(1)="ipsum" a(2)="dolor" a(3)="sit"
a(4)="amet" a(5)="consectetur" a(6)="adipiscing"
a(7)="elit" a(8)="maecenas" a(9)="varius"
a(10)="sapien" a(11)="vel" a(12)="purus"
a(13)="hendrerit" a(14)="vehicula" a(15)="integer"
a(16)="hendrerit" a(17)="viverra" a(18)="turpis" a(19)="ac"
a(20)="sagittis" a(21)="arcu" a(22)="pharetra" a(23)="id"
Test(a,24,CustomComparator)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Sort_using_a_custom_comparator.png Screenshot from Atari 8-bit computer]
<pre>
Array before sort:
[lorem ipsum dolor sit amet consectetur adipiscing elit
maecenas varius sapien vel purus hendrerit vehicula integer
hendrerit viverra turpis ac sagittis arcu pharetra id]
 
Array after sort:
[consectetur adipiscing hendrerit hendrerit maecenas
pharetra sagittis vehicula integer viverra sapien turpis varius
dolor ipsum lorem purus amet arcu elit sit vel ac id]
</pre>
 
Line 413 ⟶ 506:
{{incorrect}}
{{works with|GNAT|}}
<langsyntaxhighlight lang="ada">
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
Line 521 ⟶ 614:
Put_Line("Sorted list:");
Put(Strings);
end Custom_Compare;</langsyntaxhighlight>
{{out}}
<pre>Unsorted list:
Line 562 ⟶ 655:
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
The Algol 68 version of the Quicksort algorithm, modified to use a custom sort routine, as per this task.
<langsyntaxhighlight lang="algol68"># define the MODE that will be sorted #
MODE SITEM = STRING;
#--- Swap function ---#
Line 655 ⟶ 748:
quicksort(a, compare);
print(("After :"));FOR i FROM LWB a TO UPB a DO print((" ",a[i])) OD; print((newline))
)</langsyntaxhighlight>
{{out}}
<pre>
Line 666 ⟶ 759:
AppleScript is not itself well equipped with sorting functions, but from Yosemite onwards we can make some use of ObjC classes. While a classic comparator function can not readily be passed from AppleScript to ObjC, we can at least write a custom function which lifts atomic values into records (with keys to base and derivative values), and also passes a sequence of (key, bool) pairs, where the bool expresses the choice between ascending and descending order for the paired key:
 
<langsyntaxhighlight AppleScriptlang="applescript">use framework "Foundation"
 
-- SORTING LISTS OF ATOMIC (NON-RECORD) DATA WITH A CUSTOM SORT FUNCTION
Line 762 ⟶ 855:
sortBy(lengthDownAZup, xs)
end run</langsyntaxhighlight>
{{Out}}
<pre>{"Sao Paulo", "Shanghai", "Beijing", "Karachi", "Delhi", "Dhaka", "Lagos"}</pre>
Line 770 ⟶ 863:
Putting values into records temporarily can sometimes be necessary with ASObjC sorts so that sorting can be done on the equivalent NSDictionaries' keys. But in fact NSStrings can be sorted on the keys <tt>"length"</tt> and <tt>"self"</tt>:
 
<langsyntaxhighlight lang="applescript">use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
 
Line 780 ⟶ 873:
tell arrayOfStrings to sortUsingDescriptors:({descendingByLength, ascendingLexicographically})
 
return arrayOfStrings as list</langsyntaxhighlight>
 
{{output}}
Line 786 ⟶ 879:
 
===Vanilla===
<syntaxhighlight lang="applescript">use AppleScript version "2.3.1" -- OS X 10.9 (Mavericks) or later
use sorter : script ¬
"Custom Iterative Ternary Merge Sort" --<www.macscripter.net/t/timsort-and-nigsort/71383/3>
 
-- Sort customiser.
While vanilla AppleScript doesn't have sort facilities of its own, a customisable sort written in vanilla, such as [https://macscripter.net/viewtopic.php?pid=194430#p194430 this one on MacScripter], can be fed user-defined comparison handlers to do practically any kind of sorting. The following assumes that the customisable sort just mentioned has been compiled and saved in a suitable "Script Libraries" folder as "Custom Iterative Ternary Merge Sort.scpt":
 
<lang applescript>use AppleScript version "2.3.1" -- OS X 10.9 (Mavericks) or later
use sorter : script "Custom Iterative Ternary Merge Sort"
 
set listOfText to words of "now is the time for all good men to come to the aid of the party"
 
script descendingByLengthThenAscendingLexicographically
on isGreater(a, b)
set lenA to (count a)'s length
set lenB to (count b)'s length
if (lenA = lenB) then return (a > b)
return (alenB > blenA)
else
return (lenB > lenA)
end if
end isGreater
end script
 
set listOfText to words of "now is the time for all good men to come to the aid of the party"
-- Sort the whole list using the above customiser.
tell sorter to ¬
tell sorter to sort(listOfText, 1, -1, {comparer:descendingByLengthThenAscendingLexicographically})
sort(listOfText, 1, -1, {comparer:descendingByLengthThenAscendingLexicographically})
return listOfText</lang>
return listOfText</syntaxhighlight>
 
{{output}}
<pre>{"party", "come", "good", "time", "aid", "all", "for", "men", "now", "the", "the", "the", "is", "of", "to", "to"}</pre>
 
=={{header|ATS}}==
 
<syntaxhighlight lang="ats">(* The following demonstrates a few ways to customize the
comparator. *)
 
#include "share/atspre_staload.hats"
staload UN = "prelude/SATS/unsafe.sats"
 
%{^
#include <strings.h>
%}
 
extern fn
strcasecmp : (string, string) -<> int = "mac#strcasecmp"
 
fn
sort_strings_1 (lst : List string,
cmp : (string, string) -<> int)
:<!wrt> List string =
list_vt2t (list_mergesort_fun<string> (lst, cmp))
 
fn
sort_strings_2 (lst : List string,
cmp : (string, string) -<cloref> int)
:<!wrt> List string =
list_vt2t (list_mergesort_cloref<string> (lst, cmp))
 
fn
sort_using_a_template_function (lst : List string)
:<!wrt> List string =
(* There is no actual callback here. The comparison code is expanded
directly into the sort code. *)
let
implement
list_mergesort$cmp<string> (x, y) =
let
val m = length x
and n = length y
in
if m < n then
1
else if n < m then
~1
else
strcasecmp (x, y)
end
in
(* The list mergesort template functions in the ATS prelude return
_linear_ lists. Thus the call to list_vt2t to cast that result
to an ordinary list. *)
list_vt2t (list_mergesort<string> lst)
end
 
fn
sort_using_an_ordinary_function (lst : List string)
:<!wrt> List string =
(* Rather than expand the comparison code, incorporate a function
call into the sort implementation. *)
let
fn
cmp (x : string,
y : string)
:<> int =
let
val m = length x
and n = length y
in
if m < n then
1
else if n < m then
~1
else
strcasecmp (x, y)
end
in
list_vt2t (list_mergesort_fun<string> (lst, cmp))
end
 
fn
sort_the_way_it_works_for_qsort_in_C (lst : List string)
:<!wrt> List string =
(* Here we have a true callback to an ordinary function. *)
let
fn
cmp (x : string,
y : string)
:<> int =
let
val m = length x
and n = length y
in
if m < n then
1
else if n < m then
~1
else
strcasecmp (x, y)
end
in
sort_strings_1 (lst, cmp)
end
 
fn
sort_using_a_closure (lst : List string)
:<!wrt> List string =
(* Incorporate a closure into the sort implementation. (Standard C
does not have closures.) *)
let
fn
cmp (x : string,
y : string)
:<cloref> int =
let
val m = length x
and n = length y
in
if m < n then
1
else if n < m then
~1
else
strcasecmp (x, y)
end
in
list_vt2t (list_mergesort_cloref<string> (lst, cmp))
end
 
fn
sort_by_calling_back_to_a_closure (lst : List string)
:<!wrt> List string =
let
fn
cmp (x : string,
y : string)
:<cloref> int =
let
val m = length x
and n = length y
in
if m < n then
1
else if n < m then
~1
else
strcasecmp (x, y)
end
in
sort_strings_2 (lst, cmp)
end
 
implement
main0 () =
let
val unsorted =
$list{string}
("Here", "are", "some", "sample", "strings",
"to", "be", "sorted")
 
val sorted1 = sort_using_a_template_function unsorted
val sorted2 = sort_using_an_ordinary_function unsorted
val sorted3 = sort_the_way_it_works_for_qsort_in_C unsorted
val sorted4 = sort_using_a_closure unsorted
val sorted5 = sort_by_calling_back_to_a_closure unsorted
in
println! unsorted;
println! sorted1;
println! sorted2;
println! sorted3;
println! sorted4;
println! sorted5
end</syntaxhighlight>
 
{{out}}
<pre>$ patscc -DATS_MEMALLOC_GCBDW -O3 sort_using_custom_comparator.dats -lgc && ./a.out
Here, are, some, sample, strings, to, be, sorted
strings, sample, sorted, Here, some, are, be, to
strings, sample, sorted, Here, some, are, be, to
strings, sample, sorted, Here, some, are, be, to
strings, sample, sorted, Here, some, are, be, to
strings, sample, sorted, Here, some, are, be, to</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">numbers = 5,3,7,9,1,13,999,-4
strings = Here,are,some,sample,strings,to,be,sorted
Sort, numbers, F IntegerSort D,
Line 827 ⟶ 1,096:
StringLengthSort(a1, a2){
return strlen(a1) - strlen(a2)
}</langsyntaxhighlight>
 
=={{header|AWK}}==
For GAWK, this uses the inbuilt descending numeric ordering and a custom comparison routine for caseless string comparison.
May need modification for TAWK.
<langsyntaxhighlight AWKlang="awk"># syntax: GAWK -f SORT_USING_A_CUSTOM_COMPARATOR.AWK
#
# sorting:
Line 864 ⟶ 1,133:
l2 = tolower( i2 );
return ( ( l1 < l2 ) ? -1 : ( ( l1 == l2 ) ? 0 : 1 ) );
} # caselessCompare</langsyntaxhighlight>
{{out}}
<pre>
Line 912 ⟶ 1,181:
To sort ASCII strings, use the strsort or lexsort utilities to sort alphabetically and lexicographically, respectively.
 
<langsyntaxhighlight lang="babel">babel> ("Here" "are" "some" "sample" "strings" "to" "be" "sorted") strsort ! lsstr !
( "Here" "are" "be" "sample" "some" "sorted" "strings" "to" )
babel> ("Here" "are" "some" "sample" "strings" "to" "be" "sorted") lexsort ! lsstr !
( "be" "to" "are" "Here" "some" "sample" "sorted" "strings" )</langsyntaxhighlight>
 
If you want to sort UTF-8 encoded Unicode strings, first convert to array-string form using the str2ar operator, then sort using the strcmp operator. To sort lexicographically, use the arcmp operator. The following examples illustrate each case:
 
<langsyntaxhighlight lang="babel">babel> ("Here" "are" "some" "sample" "strings" "to" "be" "sorted") {str2ar} over ! {strcmp 0 lt?} lssort ! {ar2str} over ! lsstr !
( "Here" "are" "be" "some" "sample" "sorted" "strings" "to" )
babel> ("Here" "are" "some" "sample" "strings" "to" "be" "sorted") {str2ar} over ! {arcmp 0 lt?} lssort ! {ar2str} over ! lsstr !
( "be" "to" "are" "Here" "some" "sample" "sorted" "strings" )</langsyntaxhighlight>
 
You can sort a list of any kind of structure you like using the lssort utility. Use the lt? numerical comparison operator for sorting numerical lists:
 
<langsyntaxhighlight lang="babel">babel> ( 5 6 8 4 5 3 9 9 4 9 ) {lt?} lssort ! lsnum !
( 3 4 4 5 5 6 8 9 9 9 )</langsyntaxhighlight>
 
You can even shuffle a list with lssort using the randlf operator (your results will probably differ):
 
<langsyntaxhighlight lang="babel">babel> (1 2 3 4 5 6 7 8 9) {1 randlf 2 rem} lssort ! lsnum !
( 7 5 9 6 2 4 3 1 8 )</langsyntaxhighlight>
 
To sort complex objects, you need to access the relevant field in each object, and then provide the result of comparing them. For example, to sort a list of pairs by first number:
 
<langsyntaxhighlight lang="babel">
babel> 20 lsrange ! {1 randlf 2 rem} lssort ! 2 group ! --> this creates a shuffled list of pairs
babel> dup {lsnum !} ... --> display the shuffled list, pair-by-pair
Line 960 ⟶ 1,229:
( 15 13 )
( 17 3 )
( 18 9 )</langsyntaxhighlight>
 
=={{header|Burlesque}}==
 
<langsyntaxhighlight lang="burlesque">
blsq ) {"acb" "Abc" "Acb" "acc" "ADD"}><
{"ADD" "Abc" "Acb" "acb" "acc"}
blsq ) {"acb" "Abc" "Acb" "acc" "ADD"}(zz)CMsb
{"Abc" "acb" "Acb" "acc" "ADD"}
</syntaxhighlight>
</lang>
 
=={{header|C}}==
{{works with|POSIX|.1-2001}}
 
<langsyntaxhighlight lang="c">#include <stdlib.h> /* for qsort */
#include <string.h> /* for strlen */
#include <strings.h> /* for strcasecmp */
Line 995 ⟶ 1,264:
qsort(strings, sizeof(strings)/sizeof(*strings), sizeof(*strings), mycmp);
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
Line 1,005 ⟶ 1,274:
C# allows you to specify a custom compare to the built in sort method on a list
 
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
 
Line 1,044 ⟶ 1,313:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,086 ⟶ 1,355:
 
 
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 1,125 ⟶ 1,394:
}
}
</syntaxhighlight>
</lang>
 
=={{header|C++}}==
{{works with|g++|4.1.2}}
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <string>
#include <cctype>
Line 1,157 ⟶ 1,426:
std::sort(strings, strings+8, compare());
return 0;
}</langsyntaxhighlight>
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">shared void run() {
 
value strings = [
Line 1,173 ⟶ 1,442:
sorted.each(print);
}</langsyntaxhighlight>
 
=={{header|Clean}}==
<langsyntaxhighlight lang="clean">import StdEnv
 
less s1 s2
Line 1,186 ⟶ 1,455:
lower s = {toLower c \\ c <-: s}
 
Start = sortBy less ["This", "is", "a", "set", "of", "strings", "to", "sort"]</langsyntaxhighlight>
 
=={{header|Clojure}}==
Clojure's ''sort'' function has a 2-argument version where the first argument is a ''java.util.Comparator'', and the second is the collection to be sorted. Thus the heart of this version is a comparator function that satisfies the problem spec. What makes this work is that all Clojure functions (thus ''rosetta-code'' defined here) implement the ''java.util.Comparator'' interface.
<langsyntaxhighlight lang="clojure">(defn rosetta-compare [s1 s2]
(let [len1 (count s1), len2 (count s2)]
(if (= len1 len2)
Line 1,198 ⟶ 1,467:
(println
(sort rosetta-compare
["Here" "are" "some" "sample" "strings" "to" "be" "sorted"]))</langsyntaxhighlight>
 
{{out}}
Line 1,206 ⟶ 1,475:
 
An alternative, using <tt>sort-by</tt>:
<langsyntaxhighlight lang="clojure">(sort-by (juxt (comp - count) #(.toLowerCase %))
["Here" "are" "some" "sample" "strings" "to" "be" "sorted"])</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
Line 1,214 ⟶ 1,483:
For example, to sort strings case-insensitively in ascending order:
 
<langsyntaxhighlight lang="lisp">CL-USER> (defvar *strings*
(list "Cat" "apple" "Adam" "zero" "Xmas" "quit" "Level" "add" "Actor" "base" "butter"))
*STRINGS*
CL-USER> (sort *strings* #'string-lessp)
("Actor" "Adam" "add" "apple" "base" "butter" "Cat" "Level" "quit" "Xmas"
"zero")</langsyntaxhighlight>
 
You can also provide an optional key function which maps each element to a key. The keys are then compared using the comparator. For example, to sort strings by length in descending order:
 
<langsyntaxhighlight lang="lisp">CL-USER> (defvar *strings*
(list "Cat" "apple" "Adam" "zero" "Xmas" "quit" "Level" "add" "Actor" "base" "butter"))
*STRINGS*
CL-USER> (sort *strings* #'> :key #'length)
("butter" "apple" "Level" "Actor" "Adam" "zero" "Xmas" "quit" "base"
"Cat" "add")</langsyntaxhighlight>
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio, std.string, std.algorithm, std.typecons;
 
void main() {
Line 1,238 ⟶ 1,507:
.schwartzSort!q{ tuple(-a.length, a.toUpper) }
.writeln;
}</langsyntaxhighlight>
{{out}}
<pre>["strings", "sample", "sorted", "here", "Some", "are", "be", "to"]</pre>
Line 1,245 ⟶ 1,514:
The more natural and efficient way to solve this problem is to use <code>std.algorith.multiSort</code>.
But currently it's less convenient because it can't be used with the UFCSyntax (same output):
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.string, std.algorithm;
 
Line 1,251 ⟶ 1,520:
parts.multiSort!(q{a.length > b.length}, q{a.toUpper < b.toUpper});
parts.writeln;
}</langsyntaxhighlight>
 
=={{header|Delphi}}==
<langsyntaxhighlight Delphilang="delphi">program SortWithCustomComparator;
 
{$APPTYPE CONSOLE}
Line 1,274 ⟶ 1,543:
Result := CompareText(Left, Right);
end));
end.</langsyntaxhighlight>
 
=={{header|E}}==
<langsyntaxhighlight lang="e">/** returns a if it is nonzero, otherwise b() */
def nonzeroOr(a, b) { return if (a.isZero()) { b() } else { a } }
 
Line 1,284 ⟶ 1,553:
nonzeroOr(b.size().op__cmp(a.size()),
fn { a.compareToIgnoreCase(b) })
})</langsyntaxhighlight>
 
=={{header|EGL}}==
 
{{works with|EDT|}}
<langsyntaxhighlight EGLlang="egl">program SortExample
function main()
Line 1,325 ⟶ 1,594:
end
end</langsyntaxhighlight>
 
{{out}}
Line 1,352 ⟶ 1,621:
 
=={{header|Elena}}==
ELENA 56.0x :
<langsyntaxhighlight lang="elena">import extensions;
import system'routines;
import system'culture;
Line 1,364 ⟶ 1,633:
console.printLine("Descending length: ", items.clone()
.sort::(p,n => p.Length > n.Length).asEnumerable());
console.printLine("Ascending order: ", items.clone()
.sort::(p,n => p.toUpper(invariantLocale) < n.toUpper(invariantLocale)).asEnumerable())
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,377 ⟶ 1,646:
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">strs = ~w[this is a set of strings to sort This Is A Set Of Strings To Sort]
 
comparator = fn s1,s2 -> if String.length(s1)==String.length(s2),
Line 1,385 ⟶ 1,654:
 
# or
IO.inspect Enum.sort_by(strs, fn str -> {-String.length(str), String.downcase(str)} end)</langsyntaxhighlight>
 
{{out}}
Line 1,394 ⟶ 1,663:
 
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( sort_using_custom_comparator ).
 
Line 1,407 ⟶ 1,676:
longest_first_case_insensitive( String1, String2 ) when erlang:length(String1) =< erlang:length(String2) -> false;
longest_first_case_insensitive( _String1, _String2 ) -> true.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,416 ⟶ 1,685:
 
=={{header|Euphoria}}==
<langsyntaxhighlight lang="euphoria">include sort.e
include wildcard.e
include misc.e
Line 1,435 ⟶ 1,704:
 
puts(1,"\n\nSorted:\n")
pretty_print(1,custom_sort(routine_id("my_compare"),strings),{2})</langsyntaxhighlight>
 
{{out}}
Line 1,463 ⟶ 1,732:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let myCompare (s1:string) (s2:string) =
match compare s2.Length s1.Length with
| 0 -> compare (s1.ToLower()) (s2.ToLower())
Line 1,472 ⟶ 1,741:
let sortedStrings = List.sortWith myCompare strings
 
printfn "%A" sortedStrings</langsyntaxhighlight>
 
{{out}}
Line 1,478 ⟶ 1,747:
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">: my-compare ( s1 s2 -- <=> )
2dup [ length ] compare invert-comparison
dup +eq+ = [ drop [ >lower ] compare ] [ 2nip ] if ;
 
{ "this" "is" "a" "set" "of" "strings" "to" "sort" } [ my-compare ] sort</langsyntaxhighlight>
 
=={{header|Fantom}}==
Line 1,488 ⟶ 1,757:
The List's sort method can be customised using a custom comparator. This is a method which returns an Int: -1 for less than, 0 for equal, +1 for greater than.
 
<langsyntaxhighlight lang="fantom">
class Main
{
Line 1,509 ⟶ 1,778:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,522 ⟶ 1,791:
Fortran does not have builtin to sort arrays (of numbers or strings), with or without custom comparator; so we need modifying e.g. [[Shell sort#Fortran|this code]] in order to handle strings and to accept a custom comparator.
 
<langsyntaxhighlight lang="fortran">module sorts_with_custom_comparator
implicit none
contains
Line 1,554 ⟶ 1,823:
end do
end subroutine a_sort
end module sorts_with_custom_comparator</langsyntaxhighlight>
 
Then we have to put our custom comparator in a module (<tt>to_lower</tt> is defined [[Change string case|here]]):
 
<langsyntaxhighlight lang="fortran">module comparators
implicit none
contains
Line 1,583 ⟶ 1,852:
end if
end function my_compare
end module comparators</langsyntaxhighlight>
 
At the end, we can test these:
 
<langsyntaxhighlight lang="fortran">program CustomComparator
use comparators
use sorts_with_custom_comparator
Line 1,601 ⟶ 1,870:
print *, trim(str(i))
end do
end program CustomComparator</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' version 23-10-2016
' compile with: fbc -s console
 
Line 1,651 ⟶ 1,920:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre>strings
Line 1,661 ⟶ 1,930:
be
to</pre>
 
=={{header|Frink}}==
The program statement is somewhat naive in saying "lexicographic order" as if it a single, well-defined thing. Lexicographic sorting rules and alphabetization rules vary widely from human language to human language and require a great deal of knowledge of those rules and of Unicode to perform correctly. Frink, however, has knowledge of alphabetization (collation) rules for a large number of human languages and will make you look smart. These are encapsulated in the <CODE>lexicalCompare</CODE> and <CODE>lexicalSort</CODE> functions. By default, these compare based on the language settings defined by your Java Virtual Machine (which should be those for your human language.) The following sorts Unicode correctly according to your human language's conventions. However, see below for a more flexible example that sorts for many of the world's languages!
<syntaxhighlight lang="frink">f = {|a,b|
len = length[b] <=> length[a]
if len != 0
return len
else
return lexicalCompare[a,b]
}
 
words = split[%r/\s+/, "Here are some sample strings to be sorted"]
println[sort[words, f]]</syntaxhighlight>
{{out}}
<pre>
[strings, sample, sorted, Here, some, are, be, to]
</pre>
 
Alternately, here is a surprisingly powerful version of the sorter above that can sort based on the alphabetization rules of a very wide number of human languages. The language for the lexicographic comparison can be specified to the <CODE>lexicalCompare</CODE> function as an ISO 639-1 two-letter language code, or can be even more specific. For example, the following sorts a list of words based on the alphabetization rules for Danish.
<syntaxhighlight lang="frink">f = {|a,b,lang| lexicalCompare[a,b,lang] }
 
words = ["Ærø", "Aalborg", "Tårnby", "Vejen", "Thisted", "Stevns", "Sønderborg", "Eliasen"]
println[sort[words, f, "da"]]</syntaxhighlight>
{{out}}
<pre>
[Eliasen, Stevns, Sønderborg, Thisted, Tårnby, Vejen, Ærø, Aalborg]
</pre>
 
Note that under the lexicographic ordering rules for Danish, that order is correct, with names beginning with "Aa" alphabetized last. How many other languages handle this correctly?
 
=={{header|FunL}}==
<langsyntaxhighlight lang="funl">def preceeds( a, b ) = b.length() < a.length() or b.length() == a.length() and a.compareToIgnoreCase( b ) < 0
 
println( ["here", "are", "Some", "sample", "strings", "to", "be", "sorted"].sortWith(preceeds) )</langsyntaxhighlight>
 
{{out}}
Line 1,672 ⟶ 1,970:
["strings", "sample", "sorted", "here", "Some", "are", "be", "to"]
</pre>
 
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
local fn CustomComparator( obj1 as CFTypeRef, obj2 as CFTypeRef, context as ptr ) as NSComparisonResult
NSComparisonResult result = fn StringCaseInsensitiveCompare( obj1, obj2 )
end fn = result
 
local fn ComparatorStringSort( wordString as CFStringRef ) as CFStringRef
CFArrayRef stringArray = fn StringComponentsSeparatedByString( wordString, @" " )
CFArrayRef sortedArray = fn ArraySortedArrayUsingFunction( stringArray, @fn CustomComparator, NULL )
CFStringRef sortedStr = fn ArrayComponentsJoinedByString( sortedArray, @"\n" )
end fn = sortedStr
 
NSLog( @"%@", fn ComparatorStringSort( @"The quick brown fox jumped over the lazy dog's back" ) )
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
back
brown
dog's
fox
jumped
lazy
over
quick
The
the
</pre>
 
 
 
 
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/Sort_using_a_custom_comparator}}
 
'''Solution'''
 
[[File:Fōrmulæ - Sort using a custom comparator 01.png]]
 
[[File:Fōrmulæ - Sort using a custom comparator 02.png]]
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,700 ⟶ 2,045:
sort.Sort(s)
fmt.Println(s, "(sorted)")
}</langsyntaxhighlight>
{{out}}
<pre>[To tell your name the livelong day To an admiring bog] (original)
Line 1,707 ⟶ 2,052:
=={{header|Groovy}}==
The "custom comparator" is just a closure attached to the sort method invocation.
<langsyntaxhighlight lang="groovy">def strings = "Here are some sample strings to be sorted".split()
strings.sort { x, y ->
y.length() <=> x.length() ?: x.compareToIgnoreCase(y)
}
println strings</langsyntaxhighlight>
 
{{out}}
Line 1,718 ⟶ 2,063:
=={{header|Haskell}}==
{{works with|GHC}}
<langsyntaxhighlight lang="haskell">import Data.OrdChar (comparingtoLower)
import Data.Char (toLower)
import Data.List (sortBy)
import Data.Ord (comparing)
 
-------------------- CUSTOM COMPARATORS ------------------
 
lengthThenAZ :: String -> String -> Ordering
lengthThenAZ = comparing length `mappend`<> comparing (fmap toLower)
 
descLengthThenAZ :: String -> String -> Ordering
descLengthThenAZ = flip (comparing length) `mappend` comparing (fmap toLower)
flip (comparing length)
<> comparing (fmap toLower)
 
--------------------------- TEST -------------------------
main :: IO ()
main =
mapM_
putStrLn
( fmap
unlines
( [sortBy] <*> [lengthThenAZ, descLengthThenAZ] <*>
[["Here", "are", "some", "sample", "strings",<*> "to",[ [ "beHere", "sorted"]]))
"are",
</lang>
"some",
 
"sample",
"strings",
"to",
"be",
"sorted"
]
]
)
)</syntaxhighlight>
{{Out}}
<pre>be
Line 1,758 ⟶ 2,117:
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main() #: demonstrate various ways to sort a list and string
write("Sorting Demo for custom comparator")
L := ["Here", "are", "some", "sample", "strings", "to", "be", "sorted"]
Line 1,770 ⟶ 2,129:
procedure cmptask(a,b) # sort by descending length and ascending lexicographic order for strings of equal length
if (*a > *b) | ((*a = *b) & (map(a) << map(b))) then return b
end</langsyntaxhighlight>
 
Note(1): This example relies on [[Sorting_algorithms/Bubble_sort#Icon| the supporting procedures 'sortop', and 'demosort' in Bubble Sort]].
Line 1,803 ⟶ 2,162:
Standard utilities <tt>tolower</tt> or <tt>toupper</tt> may be substituted.
 
<langsyntaxhighlight lang="j"> mycmp=: 1 :'/:u'
length_and_lex =: (-@:# ; lower)&>
strings=: 'Here';'are';'some';'sample';'strings';'to';'be';'sorted'
Line 1,809 ⟶ 2,168:
+-------+------+------+----+----+---+--+--+
|strings|sample|sorted|Here|some|are|be|to|
+-------+------+------+----+----+---+--+--+</langsyntaxhighlight>
 
Generally speaking, J uses the concept of sorting against a normalized content (which is what <code>length_and_lex</code> provided in the above example). This eliminates a class of errors (which might be conceptualized by using a custom comparator which generates a random number: order would be non-deterministic and sorted order would depend on details of the sorting algorithm) and supports O(n) sorting algorithms such as bin sort (which cannot use comparators).
 
=={{header|Java}}==
{{works with|Java|1.5+}}
<langsyntaxhighlight lang="java5">import java.util.Comparator;
import java.util.Arrays;
 
Line 1,832 ⟶ 2,193:
System.out.print(s + " ");
}
}</langsyntaxhighlight>
 
Same thing as above
{{works with|Java|8+}}
<langsyntaxhighlight lang="java5">import java.util.Comparator;
import java.util.Arrays;
 
Line 1,853 ⟶ 2,214:
System.out.print(s + " ");
}
}</langsyntaxhighlight>
 
Using Java 11
<syntaxhighlight lang="java">
import java.util.Comparator;
import java.util.List;
 
public final class SortUsingCustomComparator {
 
public static void main(String[] args) {
List<String> list = List.of( "Here", "are", "some", "sample", "strings", "to", "be", "sorted" );
Comparator<String> custom = Comparator.comparing(String::length, Comparator.reverseOrder())
.thenComparing(Comparator.naturalOrder());
List<String> sortedList = list.stream().sorted(custom).toList();
 
System.out.println(sortedList);
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
[strings, sample, sorted, Here, some, are, be, to]
</pre>
 
=={{header|JavaScript}}==
===ES5===
<langsyntaxhighlight lang="javascript">function lengthSorter(a, b) {
var result = b.length - a.length;
if (result == 0)
Line 1,866 ⟶ 2,252:
var test = ["Here", "are", "some", "sample", "strings", "to", "be", "sorted"];
test.sort(lengthSorter);
alert( test.join(' ') ); // strings sample sorted Here some are be to</langsyntaxhighlight>
 
Or, abstracting a little for simpler composition of compound and derived searches (ASC and DESC, secondary sorts):
 
<langsyntaxhighlight lang="javascript">(function () {
'use strict';
 
Line 1,990 ⟶ 2,376:
.sort(on(flip(compare), population))
});
})();</langsyntaxhighlight>
 
===ES6===
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
 
Line 2,068 ⟶ 2,454:
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>be
Line 2,094 ⟶ 2,480:
 
As illustrated in the example, the comparator may be any jq filter, whether or not it is defined as a function.
<langsyntaxhighlight lang="jq">def quicksort(cmp):
if length < 2 then . # it is already sorted
else .[0] as $pivot
Line 2,115 ⟶ 2,501:
end )
| (.[0] | quicksort(cmp) ) + .[1] + (.[2] | quicksort(cmp) )
end ;</langsyntaxhighlight>
Example:
<langsyntaxhighlight lang="jq"># Sort by string length, breaking ties using ordinary string comparison.
["z", "yz", "ab", "c"]
| quicksort( (.[0]|length) > (.[1]|length) or ( (.[0]|length) == (.[1]|length) and .[0] < .[1] ) )
</syntaxhighlight>
</lang>
{{Out}}
<langsyntaxhighlight lang="jq">[
"ab",
"yz",
"c",
"z"
]</langsyntaxhighlight>
 
=={{header|Julia}}==
My word list source is the opening sentence of Shelly's [http://www.gutenberg.org/cache/epub/84/pg84.txt Frankenstein].
<langsyntaxhighlight lang="julia">wl = filter(!isempty, split("""You will rejoice to hear that no disaster has accompanied the
commencement of an enterprise which you have regarded with such evil
forebodings.""", r"\W+"))
Line 2,138 ⟶ 2,524:
sort!(wl; by=x -> (-length(x), lowercase(x)))
println("\nSorted list:\n - ", join(wl, "\n - "))
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,195 ⟶ 2,581:
A translation from Java, also showing the seamless interop between Java and Kotlin code.
 
<langsyntaxhighlight lang="kotlin">import java.util.Arrays
 
fun main(args: Array<String>) {
Line 2,212 ⟶ 2,598:
Arrays.sort(strings) { first, second ->
val lengthDifference = second.length - first.length
if (lengthDifference == 0) first.lowercase().compareTo(second.lowercase(), true) else lengthDifference
}
 
printArray("Sorted:", strings)
}</langsyntaxhighlight>
 
{{out}}
Line 2,225 ⟶ 2,611:
A more idiomatic version (1.3):
 
<langsyntaxhighlight lang="kotlin">fun main(args: Array<String>) {
val strings = listOf("Here", "are", "some", "sample", "strings", "to", "be", "sorted")
println("Unsorted: $strings")
 
// sort by content first then by length => no need for a custom comparator since sortedByDescending is stable
val sorted = strings.sortedsortedBy { it.lowercase() }.sortedByDescending { it.length }
 
println("Sorted: $sorted")
}</langsyntaxhighlight>
 
 
Using a custom comparator as requested by task description:
 
<langsyntaxhighlight lang="kotlin">fun main(args: Array<String>) {
val strings = listOf("Here", "are", "some", "sample", "strings", "to", "be", "sorted")
println("Unsorted: $strings")
 
val sorted = strings.sortedWith ({ a, b ->
kotlin.Comparator { a, b ->
compareValues(b.length, a.length).let {
if (it == 0) compareValues(a.lowercase(), b.lowercase())
else it
}
})
println("Sorted: $sorted")
}</langsyntaxhighlight>
 
 
Faster when computing length and lowercase only once per value ([[wp:Schwartzian transform|Schwartzian transform]]):
 
<langsyntaxhighlight lang="kotlin">fun main(args: Array<String>) {
val strings = listOf("Here", "are", "some", "sample", "strings", "to", "be", "sorted")
println("Unsorted: $strings")
 
val sorted = strings.map { PairTriple(it, it.length, it.lowercase()) }.sortedWith ({ a, b ->
kotlin.Comparator { a, b ->
compareValues(b.second, a.second).let {
if (it == 0) compareValues(a.firstthird, b.firstthird)
else it
}
}).map { it.first }
 
println("Sorted: $sorted")
}</langsyntaxhighlight>
 
 
{{out}}
<pre>Unsorted: [Here, are, some, sample, strings, to, be, sorted]
Sorted: [strings, sample, sorted, Here, some, are, be, to]</pre>
 
=={{header|Lambdatalk}}==
<syntaxhighlight lang="scheme">
 
{def sortbylength
 
{def sortbylength.i
{lambda {:x :a}
{if {A.empty? :a}
then {A.new :x}
else {if {> {W.length :x} {W.length {A.first :a}}}
then {A.addfirst! :x :a}
else {A.addfirst! {A.first :a}
{sortbylength.i :x {A.rest :a}}} }}}}
 
{def sortbylength.r
{lambda {:a1 :a2}
{if {A.empty? :a1}
then :a2
else {sortbylength.r {A.rest :a1}
{sortbylength.i {A.first :a1} :a2}} }}}
 
{lambda {:s}
{S.replace (\[|\]) by in
{S.replace , by space in
{A.disp {sortbylength.r {A.new :s} {A.new}} }}}}}
-> sortbylength
 
{sortbylength here are Some sample strings to be sorted}
-> strings sample sorted here Some are to be
</syntaxhighlight>
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">test = { "Here", "we", "have", "some", "sample", "strings", "to", "be", "sorted" }
 
function stringSorter(a, b)
Line 2,285 ⟶ 2,703:
 
-- print sorted table
for k,v in pairs(test) do print(v) end</langsyntaxhighlight>
 
{{out}}
Line 2,294 ⟶ 2,712:
 
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Checkit {
Class Quick {
Line 2,374 ⟶ 2,792:
}
Checkit
</syntaxhighlight>
</lang>
 
ForStringsSpecial can be coded using a Compare(aj$, lx$). See the use of break to break cases in select cases.
Any case in Select case may have one statement (if then is one statement), or a block of code. We can leave a case with a blank line after, a one statement line, or a block of code, or a case statement. A break statement break cases, so all code executed, until a continue found, to exit from Select (next statement after End Select). We use a sub to make two statements as one.
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Group Quick {
Module ForStringsSpecial {
Line 2,408 ⟶ 2,826:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,450 ⟶ 2,868:
 
=={{header|Maple}}==
<langsyntaxhighlight Maplelang="maple">Compare_fn:= proc(s1, s2)
local len1, len2;
len1 := StringTools:-Length(s1);
Line 2,464 ⟶ 2,882:
 
L := ["Here", "are", "some", "sample", "strings", "to", "be", "sorted", "Tooo"];
sort(L, Compare_fn);</langsyntaxhighlight>
{{out}}
<pre>
Line 2,471 ⟶ 2,889:
 
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
We define a new function to give true or false if two elements are in order.
After that we can simply use the built-in Sort with an ordering function:
<langsyntaxhighlight Mathematicalang="mathematica">StringOrderQ[x_String, y_String] :=
If[StringLength[x] == StringLength[y],
OrderedQ[{x, y}],
Line 2,480 ⟶ 2,898:
]
words={"on","sunday","sander","sifted","and","sorted","sambaa","for","a","second"};
Sort[words,StringOrderQ]</langsyntaxhighlight>
gives back:
<pre>{sambaa,sander,second,sifted,sorted,sunday,and,for,on,a}</pre>
 
=={{header|Maxima}}==
<langsyntaxhighlight lang="maxima">strangeorderp(a, b) := slength(a) > slength(b) or (slength(a) = slength(b) and orderlessp(a, b))$
s: tokens("Lorem ipsum dolor sit amet consectetur adipiscing elit Sed non risus Suspendisse\
lectus tortor dignissim sit amet adipiscing nec ultricies sed dolor")$
Line 2,492 ⟶ 2,910:
["Suspendisse", "consectetur", "adipiscing", "adipiscing", "dignissim", "ultricies",
"lectus", "tortor", "Lorem", "dolor", "dolor", "ipsum", "risus", "amet", "amet",
"elit", "Sed", "nec", "non", "sed", "sit", "sit"]</langsyntaxhighlight>
 
=={{header|MAXScript}}==
<langsyntaxhighlight lang="maxscript">fn myCmp str1 str2 =
(
case of
Line 2,517 ⟶ 2,935:
strList = #("Here", "are", "some", "sample", "strings", "to", "be", "sorted")
qSort strList myCmp
print strList</langsyntaxhighlight>
 
=={{header|min}}==
{{works with|min|0.19.3}}
<langsyntaxhighlight lang="min">("Here" "are" "some" "sample" "strings" "to" "be" "sorted")
(((length) (length)) spread <) sort print</langsyntaxhighlight>
{{out}}
<pre>
Line 2,529 ⟶ 2,947:
 
=={{header|Nemerle}}==
<langsyntaxhighlight Nemerlelang="nemerle">using System.Console;
 
module CustomSort
Line 2,541 ⟶ 2,959:
WriteLine(strings2.Sort((x, y) => x.CompareTo(y)))
}
}</langsyntaxhighlight>
{{out}}
<pre>[different, strings, length, these, are, of]
Line 2,548 ⟶ 2,966:
=={{header|NetRexx}}==
{{trans|Java}}
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 2,580 ⟶ 2,998:
else signal IllegalArgumentException('Arguments must be Strings')
return cRes
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,588 ⟶ 3,006:
 
=={{header|Nial}}==
<langsyntaxhighlight lang="nial">sort fork [=[tally first,tally last],up, >= [tally first,tally last]] ['Here', 'are', 'some', 'sample', 'strings', 'to', 'be', 'sorted']
=+-------+------+------+----+----+---+--+--+
=|strings|sample|sorted|Here|some|are|be|to|
=+-------+------+------+----+----+---+--+--+</langsyntaxhighlight>
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import strutils, algorithm
 
var strings = "here are Some sample strings to be sorted".split(' ')
Line 2,604 ⟶ 3,022:
)
 
echo strings</langsyntaxhighlight>
 
{{out}}
Line 2,610 ⟶ 3,028:
 
=={{header|Objeck}}==
<langsyntaxhighlight lang="objeck">use Collection;
 
class Test {
Line 2,666 ⟶ 3,084:
return @s;
}
}</langsyntaxhighlight>
 
<pre>
Line 2,676 ⟶ 3,094:
{{works with|Cocoa|Mac OS X 10.6+}}
Using blocks:
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
 
#define esign(X) (((X)>0)?1:(((X)<0)?-1:0))
Line 2,703 ⟶ 3,121:
}
return EXIT_SUCCESS;
}</langsyntaxhighlight>
 
 
Line 2,709 ⟶ 3,127:
 
{{works with|Cocoa}}
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
 
@interface NSString (CustomComp)
Line 2,744 ⟶ 3,162:
}
return EXIT_SUCCESS;
}</langsyntaxhighlight>
 
This example can also be written using sort descriptors:
{{works with|GNUstep}}
{{works with|Cocoa}}
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
 
int main()
Line 2,766 ⟶ 3,184:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let mycmp s1 s2 =
if String.length s1 <> String.length s2 then
compare (String.length s2) (String.length s1)
else
String.compare (String.lowercase s1) (String.lowercase s2)</langsyntaxhighlight>
 
List:
<langsyntaxhighlight lang="ocaml"># let strings = ["Here"; "are"; "some"; "sample"; "strings"; "to"; "be"; "sorted"];;
val strings : string list =
["Here"; "are"; "some"; "sample"; "strings"; "to"; "be"; "sorted"]
# List.sort mycmp strings;;
- : string list =
["strings"; "sample"; "sorted"; "Here"; "some"; "are"; "be"; "to"]</langsyntaxhighlight>
 
Array:
<langsyntaxhighlight lang="ocaml"># let strings = [|"Here"; "are"; "some"; "sample"; "strings"; "to"; "be"; "sorted"|];;
val strings : string array =
[|"Here"; "are"; "some"; "sample"; "strings"; "to"; "be"; "sorted"|]
Line 2,791 ⟶ 3,209:
# strings;;
- : string array =
[|"strings"; "sample"; "sorted"; "Here"; "some"; "are"; "be"; "to"|]</langsyntaxhighlight>
 
=={{header|Oforth}}==
 
<langsyntaxhighlight Oforthlang="oforth">String method: customCmp(s)
s size self size > ifTrue: [ true return ]
s size self size < ifTrue: [ false return ]
Line 2,801 ⟶ 3,219:
 
["this", "is", "a", "set", "of", "strings", "to", "sort", "This", "Is", "A", "Set", "Of", "Strings", "To", "Sort"]
sortWith(#customCmp) println</langsyntaxhighlight>
 
{{out}}
Line 2,807 ⟶ 3,225:
[Strings, strings, Sort, sort, this, This, Set, set, is, Is, of, Of, To, to, A, a]
</pre>
 
=={{header|Ol}}==
<syntaxhighlight lang="scheme">
(import (scheme char))
 
(define (comp a b)
(let ((la (string-length a))
(lb (string-length b)))
(or
(> la lb)
(and (= la lb) (string-ci<? a b)))))
 
(print
(sort comp '(
"lorem" "ipsum" "dolor" "sit" "amet" "consectetur"
"adipiscing" "elit" "maecenas" "varius" "sapien"
"vel" "purus" "hendrerit" "vehicula" "integer"
"hendrerit" "viverra" "turpis" "ac" "sagittis"
"arcu" "pharetra" "id")))
</syntaxhighlight>
 
=={{header|ooRexx}}==
<langsyntaxhighlight ooRexxlang="oorexx">A=.array~of('The seven deadly sins','Pride','avarice','Wrath','envy','gluttony','sloth','Lust')
say 'Sorted in order of descending length, and in ascending lexicographic order'
say A~sortWith(.DescLengthAscLexical~new)~makeString
Line 2,818 ⟶ 3,256:
if left~length==right~length
then return left~caselessCompareTo(right)
else return right~length-left~length</langsyntaxhighlight>
{{out}}
<pre>
Line 2,831 ⟶ 3,269:
Lust
</pre>
 
=={{header|OxygenBasic}}==
<syntaxhighlight lang="text">
uses generics 'containing sort macros
uses console
string sdata={"CC","Aa","aAa","bb","bbB","b","B","c","A"}
'
int count = countof sdata
'
macro filter(f,a)
=================
'sdata[a]
f=1 'allow all
end macro
'
macro compare(f,a,b)
====================
int la=len sdata[a]
int lb=len sdata[b]
if la<lb
f=1 'descending length
elseif la>lb
'
elseif ucase(sdata[a])>ucase(sdata[b])
f=1 'ascending but case insensitive
endif
end macro
'
NewSortIndex(index,count,rcount,filter,compare)
NewSortedData(sorted,sdata,index,rcount)
'
print "Count: " rcount cr cr
int i
for i=1 to rcount
print sorted[i] cr
next
pause
</syntaxhighlight>
 
=={{header|Oz}}==
<langsyntaxhighlight lang="oz">declare
fun {LexicographicLessThan Xs Ys}
for
Line 2,853 ⟶ 3,329:
Strings = ["Here" "are" "some" "sample" "strings" "to" "be" "sorted"]
in
{ForAll {Sort Strings LessThan} System.showInfo}</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">cmp(a,b)=if(#a<#b,1,if(#a>#b,-1,lex(a,b)));
vecsort(v,cmp)</langsyntaxhighlight>
 
=={{header|Pascal}}==
{{works with|Free Pascal}}
<syntaxhighlight lang="pascal">
See at http://rosettacode.org/wiki/Sorting_algorithms/Merge_sort#improvement struct/record with myText implementing this task too
program CustomComparator;
{$mode objfpc}{$h+}
uses
Classes, SysUtils, Math;
 
function Compare(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := CompareValue(Length(List[Index2]), Length(List[Index1]));
if Result = 0 then
Result := CompareText(List[Index1], List[Index2]);
end;
 
const
Sample = 'Here are some sample strings to be sorted';
 
begin
with TStringList.Create do
try
AddStrings(Sample.Split([' '], TStringSplitOptions.ExcludeEmpty));
CustomSort(@Compare);
WriteLn(string.Join(', ', ToStringArray));
finally
Free;
end;
Readln;
end.
</syntaxhighlight>
{{out}}
<pre>
strings, sample, sorted, Here, some, are, be, to
</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use feature 'say';
 
@strings = qw/Here are some sample strings to be sorted/;
Line 2,879 ⟶ 3,386:
sort { $b->[1] <=> $a->[1] || $a->[2] cmp $b->[2] }
map { [ $_, length, lc ] }
@strings;</langsyntaxhighlight>
{{out}}
<pre>strings sample sorted Here some are be to
Line 2,887 ⟶ 3,394:
=={{header|Phix}}==
{{libheader|Phix/basics}}
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #008080;">function</span> <span style="color: #000000;">my_compare</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #7060A8;">compare</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- descending length</span>
Line 2,896 ⟶ 3,403:
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">custom_sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">my_compare</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Here"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"are"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"some"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"sample"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"strings"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"to"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"be"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"sorted"</span><span style="color: #0000FF;">})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 2,904 ⟶ 3,411:
=={{header|PHP}}==
{{works with|PHP|4.4.4 CLI}}
<langsyntaxhighlight lang="php"><?php
function mycmp($s1, $s2)
{
Line 2,914 ⟶ 3,421:
$strings = array("Here", "are", "some", "sample", "strings", "to", "be", "sorted");
usort($strings, "mycmp");
?></langsyntaxhighlight>
 
=={{header|PicoLisp}}==
Line 2,920 ⟶ 3,427:
PicoLisp returns an ascending list (of any type). To get a result in descending
order, the "greater than" function can be supplied
<langsyntaxhighlight PicoLisplang="picolisp">: (sort '("def" "abc" "ghi") >)
-> ("ghi" "def" "abc")</langsyntaxhighlight>
or simply the result reversed (which is, btw, the most efficient way)
<langsyntaxhighlight PicoLisplang="picolisp">: (flip (sort '("def" "abc" "ghi")))
-> ("ghi" "def" "abc")</langsyntaxhighlight>
 
=={{header|PL/I}}==
Line 2,930 ⟶ 3,437:
 
'''Platform:''' [[WIN]]
<langsyntaxhighlight lang="pli">MRGEPKG: package exports(MERGESORT,MERGE,RMERGE);
 
DCL (T(4)) CHAR(20) VAR; /* scratch space of length N/2 */
Line 2,999 ⟶ 3,506:
 
put skip;
END RMERGE;</langsyntaxhighlight>
 
=={{header|Pop11}}==
<langsyntaxhighlight lang="pop11">lvars ls = ['Here' 'are' 'some' 'sample' 'strings' 'to' 'be' 'sorted'];
define compare(s1, s2);
lvars k = length(s2) - length(s1);
Line 3,022 ⟶ 3,529:
l2 = length(s2);
l1 > l2 or (l1 == l2 and alphabefore(uppertolower(s1), uppertolower(s2)))
enddefine;</langsyntaxhighlight>
 
=={{header|PowerBASIC}}==
Line 3,028 ⟶ 3,535:
{{works with|PB/CC|4}}
 
<langsyntaxhighlight lang="powerbasic">FUNCTION Sorter(p1 AS STRING, p2 AS STRING) AS LONG
'if p1 should be first, returns -1
'if p2 should be first, returns 1
Line 3,053 ⟶ 3,560:
'pb's built-in sorting; "USING" tells it to use our custom comparator
ARRAY SORT x(), USING Sorter()
END FUNCTION</langsyntaxhighlight>
 
=={{header|PowerShell}}==
The <code>Sort-Object</code> cmdlet accepts script blocks as arguments as well as multiple criteria after which to sort.
<langsyntaxhighlight lang="powershell">$list = "Here", "are", "some", "sample", "strings", "to", "be", "sorted"
$list | Sort-Object {-$_.Length},{$_}</langsyntaxhighlight>
The negated string length is the first sort criterion, the second is the string itself, resulting in descending length and ascending lexicographic order.
 
=={{header|Prolog}}==
Works with SWI-Prolog (Tested on Version 8.1.19). Duplicates (if any) are removed.
<langsyntaxhighlight Prologlang="prolog">rosetta_sort :-
L = ["Here", "are", "some", "sample", "strings", "to", "be", "sorted" ],
predsort(my_comp, L, L1),
Line 3,081 ⟶ 3,588:
my_write(W) :-
format('~s ', [W]).
</syntaxhighlight>
</lang>
 
{{out}}
Line 3,095 ⟶ 3,602:
=={{header|Python}}==
Using a key function is usually more efficient than a comparator. We can take advantage of the fact that tuples are ordered first by the first element, then by the second, etc., to perform a sort on multiple criteria.
<langsyntaxhighlight lang="python">strings = "here are Some sample strings to be sorted".split()
 
def mykey(x):
return -len(x), x.upper()
 
print sorted(strings, key=mykey)</langsyntaxhighlight>
 
{{out}}
<langsyntaxhighlight lang="python">['strings', 'sample', 'sorted', 'here', 'Some', 'are', 'be', 'to']</langsyntaxhighlight>
 
===Alternative method using cmp===
To technically comply with this task, we can also use an actual comparator (''cmp'') function which will be called every time members of the original list are to be compared. Note that this feature is worse than using the key argument and has been removed from Python 3, so should no longer be used in new code.
<langsyntaxhighlight lang="python">def mycmp(s1, s2):
return cmp(len(s2), len(s1)) or cmp(s1.upper(), s2.upper())
 
print sorted(strings, cmp=mycmp)</langsyntaxhighlight>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="quackery"> [ $ "" swap
witheach
[ upper join ] ] is upper$ ( $ --> )
 
[ over size over size
2dup = iff
[ 2drop upper$
swap upper$ $< ]
else
[ 2swap 2drop < ] ] is comparator ( $ $ -- b )
 
$ ‘here are Some sample strings to be sorted’
nest$ sortwith comparator
witheach [ echo$ sp ]
cr cr
$ "sharna pax and hed on a poal when the ardship of Cambry come out of his hoal"
nest$ sortwith comparator
witheach [ echo$ sp ]</syntaxhighlight>
 
{{out}}
 
<pre>strings sample sorted here Some are be to
 
ardship Cambry sharna come hoal poal when and hed his out pax the of of on a </pre>
 
=={{header|R}}==
 
<langsyntaxhighlight Rlang="r">v = c("Here", "are", "some", "sample", "strings", "to", "be", "sorted")
print(v[order(-nchar(v), tolower(v))])</langsyntaxhighlight>
 
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 3,135 ⟶ 3,669:
(sort2 '("Some" "pile" "of" "words"))
;; -> '("words" "pile" "Some" "of")
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)<br>
Primary sort by length of string, then break ties by sorting alphabetically (ignoring case).
<syntaxhighlight lang="raku" perl6line>my @strings = <Here are some sample strings to be sorted>;
put @strings.sort:{.chars, .lc};
put sort -> $x { $x.chars, $x.lc }, @strings;</langsyntaxhighlight>
{{out}}
<pre>be to are Here some sample sorted strings
Line 3,149 ⟶ 3,683:
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program sorts a (stemmed) array using the merge-sort method. */
/* using mycmp function for the sort order */
/**********************************************************************
Line 3,278 ⟶ 3,812:
Otherwise res=0
End
RETURN res</langsyntaxhighlight>
{{out}}
<pre>
Line 3,304 ⟶ 3,838:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
load "stdlib.ring"
 
Line 3,339 ⟶ 3,873:
see oList[n] [1] + nl
next
</syntaxhighlight>
</lang>
Output:
<pre>
Line 3,355 ⟶ 3,889:
Since Ruby 1.8.6 Enumerables have a "sort_by" method, taking a key block, which is more efficient than a comparator. We can take advantage of the fact that Arrays are ordered first by the first element, then by the second, etc., to perform a sort on multiple criteria.
 
<langsyntaxhighlight lang="ruby">words = %w(Here are some sample strings to be sorted)
p words.sort_by {|word| [-word.size, word.downcase]}</langsyntaxhighlight>
 
To technically comply with this task, we can also use an actual comparator block which will be called every time members of the original list are to be compared.
<langsyntaxhighlight lang="ruby">p words.sort {|a, b| d = b.size <=> a.size
d != 0 ? d : a.upcase <=> b.upcase}</langsyntaxhighlight>
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">
fn main() {
let mut words = ["Here", "are", "some", "sample", "strings", "to", "be", "sorted"];
Line 3,369 ⟶ 3,903:
println!("{:?}", words);
}
</syntaxhighlight>
</lang>
 
=={{header|Sather}}==
<langsyntaxhighlight lang="sather">class MAIN is
 
custom_comp(a, b:STR):BOOL is
Line 3,386 ⟶ 3,920:
loop #OUT + s.elt! + "\n"; end;
end;
end;</langsyntaxhighlight>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">List("Here", "are", "some", "sample", "strings", "to", "be", "sorted").sortWith{(a,b) =>
val cmp=a.size-b.size
(if (cmp==0) -a.compareTo(b) else cmp) > 0
}</langsyntaxhighlight>
{{out}}
<pre>List(strings, sample, sorted, Here, some, are, be, to)</pre>
 
=={{header|Scheme}}==
<langsyntaxhighlight lang="scheme">(use srfi-13);;Syntax for module inclusion depends on implementation,
;;a sort function may be predefined, or available through srfi 95
(define (mypred? a b)
Line 3,406 ⟶ 3,940:
(> len-a len-b))))
 
(sort '("sorted" "here" "strings" "sample" "Some" "are" "be" "to") mypred?) </langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="scheme">("strings" "sample" "sorted" "here" "Some" "are" "be" "to")</langsyntaxhighlight>
 
 
Line 3,414 ⟶ 3,948:
{{works with|Gauche Scheme}}
 
<langsyntaxhighlight Schemelang="scheme">(define strings '(
"This" "Is" "A" "Set" "Of" "Strings" "To" "Sort" "duplicated"
"this" "is" "a" "set" "of" "strings" "to" "sort" "duplicated"))
Line 3,425 ⟶ 3,959:
(apply string-ci<? two)
(apply > sizes)))))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,433 ⟶ 3,967:
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func mycmp(a, b) { (b.len <=> a.len) || (a.lc <=> b.lc) };
var strings = %w(Here are some sample strings to be sorted);
var sorted = strings.sort(mycmp);</langsyntaxhighlight>
 
=={{header|Slate}}==
<langsyntaxhighlight lang="slate">define: #words -> #('here' 'are' 'some' 'sample' 'strings' 'to' 'sort' 'since' 'this' 'exercise' 'is' 'not' 'really' 'all' 'that' 'dumb' '(sorry)').
words sortBy: [| :first :second | (first lexicographicallyCompare: second) isNegative]</langsyntaxhighlight>
 
=={{header|Smalltalk}}==
<langsyntaxhighlight lang="smalltalk">#('here' 'are' 'some' 'sample' 'strings' 'to' 'sort' 'since' 'this' 'exercise' 'is' 'not' 'really' 'all' 'that' 'dumb' '(sorry)' ) asSortedCollection
sortBlock:
[:first :second | (second size = first size)
ifFalse: [second size < first size]
ifTrue: [first < second]]</langsyntaxhighlight>
the above creates a sorted collection;
an inplace sort of arrayed collections is done with eg.:
<langsyntaxhighlight lang="smalltalk">#('here' 'are' 'some' 'sample' 'strings')
sort:[:a :b | a reversed < b reversed]</langsyntaxhighlight>
 
=={{header|Standard ML}}==
List:
{{works with|SML/NJ}}
<langsyntaxhighlight lang="sml">fun mygt (s1, s2) =
if size s1 <> size s2 then
size s2 > size s1
else
String.map Char.toLower s1 > String.map Char.toLower s2</langsyntaxhighlight>
 
<langsyntaxhighlight lang="sml">- val strings = ["Here", "are", "some", "sample", "strings", "to", "be", "sorted"];
val strings = ["Here","are","some","sample","strings","to","be","sorted"]
: string list
- ListMergeSort.sort mygt strings;
val it = ["strings","sample","sorted","Here","some","are","be","to"]
: string list</langsyntaxhighlight>
 
Array:
{{works with|SML/NJ}}
<langsyntaxhighlight lang="sml">fun mycmp (s1, s2) =
if size s1 <> size s2 then
Int.compare (size s2, size s1)
else
String.compare (String.map Char.toLower s1, String.map Char.toLower s2)</langsyntaxhighlight>
 
<langsyntaxhighlight lang="sml">- val strings = Array.fromList ["Here", "are", "some", "sample", "strings", "to", "be", "sorted"];
val strings = [|"Here","are","some","sample","strings","to","be","sorted"|]
: string array
Line 3,483 ⟶ 4,017:
- strings;
val it = [|"strings","sample","sorted","Here","some","are","be","to"|]
: string array</langsyntaxhighlight>
 
=={{header|Swift}}==
{{works with|Swift|2.x+}}
<langsyntaxhighlight lang="swift">import Foundation
 
var list = ["this",
Line 3,516 ⟶ 4,050:
return lhsCount > rhsCount
}</langsyntaxhighlight>
{{works with|Swift|1.2}}
<langsyntaxhighlight lang="swift">import Foundation
 
var list = ["this",
Line 3,547 ⟶ 4,081:
return lhsCount > rhsCount
}</langsyntaxhighlight>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc sorter {a b} {
set la [string length $a]
set lb [string length $b]
Line 3,562 ⟶ 4,096:
 
set strings {here are Some sample strings to be sorted}
lsort -command sorter $strings ;# ==> strings sample sorted here Some are be to</langsyntaxhighlight>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
setofstrings="this is a set of strings to sort This Is A Set Of Strings To Sort"
Line 3,579 ⟶ 4,113:
PRINT "2. setofstrings sorted"
*{sorted}
</syntaxhighlight>
</lang>
{{out}}
<pre style='height:30ex;overflow:scroll'>
Line 3,622 ⟶ 4,156:
The less or equal length predicate (leql) and lexically less or equal predicate (lleq) are also standard library functions. This task is therefore easily dispatched as shown.
 
<langsyntaxhighlight Ursalalang="ursala">#import std
#show+
 
data = <'this','is','a','list','of','strings','to','be','sorted'>
 
example = psort<not leql,lleq+ ~* ~&K31K30piK26 letters> data</langsyntaxhighlight>
The lleq library function is case sensitive, so it is composed with a function to convert the words to lower case on the fly (without destructively modifying them) in order to meet the task requirement of case insensitivity.
 
Line 3,643 ⟶ 4,177:
=={{header|Visual Basic .NET}}==
 
<langsyntaxhighlight lang="vbnet">Imports System
 
Module Sorting_Using_a_Custom_Comparator
Line 3,660 ⟶ 4,194:
Array.Sort(strings, New Comparison(Of String)(AddressOf CustomComparator))
End Sub
End Module</langsyntaxhighlight>
 
=={{header|Wren}}==
{{libheader|Wren-sort}}
<langsyntaxhighlight ecmascriptlang="wren">import "./sort" for Cmp, Sort
 
var cmp = Fn.new { |s, t|
Line 3,675 ⟶ 4,209:
System.print("Unsorted: %(strings)")
Sort.insertion(strings, cmp)
System.print("Sorted : %(strings)")</langsyntaxhighlight>
 
{{out}}
Line 3,681 ⟶ 4,215:
Unsorted: [Here, are, some, sample, strings, to, be, sorted]
Sorted : [strings, sample, sorted, Here, some, are, be, to]
</pre>
 
=={{header|Zig}}==
'''Works with:''' 0.11.x, 0.12.0-dev.1390+94cee4fb2
 
For 0.10.x, replace std.mem.sort with std.sort.sort .
 
<syntaxhighlight lang="zig">const std = @import("std");
 
/// Sort by descending length and ascending lexicographical order.
/// If true, element will remain on it's place.
fn lessThanFn(context: void, left: []const u8, right: []const u8) bool {
_ = context;
// Sort by descending length
switch (std.math.order(left.len, right.len)) {
.lt => return false,
.eq => {},
.gt => return true,
}
 
// If length is equal, sort by ascending lexicographical order
return switch (std.ascii.orderIgnoreCase(left, right)) {
.lt => true,
.eq => false,
.gt => false,
};
}
 
pub fn main() void {
var words = [_][]const u8{ "Here", "are", "some", "sample", "strings", "to", "be", "sorted" };
 
std.debug.print("Before: [ ", .{});
for (words) |word| {
std.debug.print("\"{s}\" ", .{word});
}
std.debug.print("]\n", .{});
 
std.mem.sort([]const u8, &words, {}, lessThanFn);
 
std.debug.print("After: [ ", .{});
for (words) |word| {
std.debug.print("\"{s}\" ", .{word});
}
std.debug.print("]\n", .{});
}</syntaxhighlight>
 
{{out}}
<pre>
Before: [ "Here" "are" "some" "sample" "strings" "to" "be" "sorted" ]
After: [ "strings" "sample" "sorted" "Here" "some" "are" "be" "to" ]
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">s:=T("Cat","apple","Adam","zero","Xmas","quit","Level","add","Actor","base","butter");
r:=s.sort(fcn(a,b){
an,bn := a.len(),b.len();
if(an==bn)(a.toLower() < b.toLower()) else (an > bn)
});
r.pump(Console.println);</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits