Sort an array of composite structures: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Wren}}: Minor tidy)
 
(28 intermediate revisions by 17 users not shown)
Line 1: Line 1:
{{task|Sorting}}
{{task|Sorting Algorithms}}
{{Sorting Algorithm}}
[[Category:Sorting]]


Sort an array of composite structures by a key.
Sort an array of composite structures by a key.
Line 12: Line 14:
and an array of such pairs:
and an array of such pairs:


x: array of pairs
x: array of pairs


then define a sort routine that sorts the array ''x'' by the key ''name''.
then define a sort routine that sorts the array ''x'' by the key ''name''.


This task can always be accomplished with [[Sorting Using a Custom Comparator]]. If your language is not listed here, please see the other article.
This task can always be accomplished with [[Sorting Using a Custom Comparator]].

If your language is not listed here, please see the other article.
<br><br>
<br><br>
=={{header|11l}}==
{{trans|Kotlin}}

<syntaxhighlight lang="11l">T Employee
String name, category

F (name, category)
.name = name
.category = category

V employees = [
Employee(‘David’, ‘Manager’),
Employee(‘Alice’, ‘Sales’),
Employee(‘Joanna’, ‘Director’),
Employee(‘Henry’, ‘Admin’),
Employee(‘Tim’, ‘Sales’),
Employee(‘Juan’, ‘Admin’)
]

employees.sort(key' e -> e.name)

L(e) employees
print(‘#<6 : #.’.format(e.name, e.category))</syntaxhighlight>

{{out}}
<pre>
Alice : Sales
David : Manager
Henry : Admin
Joanna : Director
Juan : Admin
Tim : Sales
</pre>

=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits}}
<syntaxhighlight lang="aarch64 assembly">
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program shellSort64.s */
/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"

/*******************************************/
/* Structures */
/********************************************/
/* city structure */
.struct 0
city_name: //
.struct city_name + 8 // string pointer
city_habitants: //
.struct city_habitants + 8 // integer
city_end:
/*********************************/
/* Initialized data */
/*********************************/
.data
sMessResult: .asciz "Name : @ number habitants : @ \n"
szMessSortHab: .asciz "Sort table for number of habitants :\n"
szMessSortName: .asciz "Sort table for name of city :\n"
szCarriageReturn: .asciz "\n"

// cities name
szCeret: .asciz "Ceret"
szMaureillas: .asciz "Maureillas"
szTaillet: .asciz "Taillet"
szReynes: .asciz "Reynes"
szVives: .asciz "Vivés"
szBoulou: .asciz "Le Boulou"
szSaintJean: .asciz "Saint Jean Pla de Corts"
szCluses: .asciz "Les Cluses"
szAlbere: .asciz "L'Albère"
szPerthus: .asciz "Le Perthus"

.align 4
TableCities:
.quad szCluses // address name string
.quad 251 // number of habitants
.quad szCeret
.quad 7705
.quad szMaureillas
.quad 2596
.quad szBoulou
.quad 5554
.quad szSaintJean
.quad 2153
.quad szAlbere
.quad 83
.quad szVives
.quad 174
.quad szTaillet
.quad 115
.quad szPerthus
.quad 586
.quad szReynes
.quad 1354
.equ NBELEMENTS, (. - TableCities) / city_end
.skip city_end // temp area for element in shellSort
// see other soluce to use stack
// in programm arm assembly in this forum
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
sZoneConv: .skip 24
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: // entry of program
ldr x0,qAdrszMessSortHab
bl affichageMess

ldr x0,qAdrTableCities // address table
mov x1,0 // not use in routine
mov x2,NBELEMENTS // number of élements
mov x3,#city_habitants // sort by number habitants
mov x4,#'N' // numeric
bl shellSort
ldr x0,qAdrTableCities // address table
bl displayTable
ldr x0,qAdrszMessSortName
bl affichageMess

ldr x0,qAdrTableCities // address table
mov x1,0 // not use in routine
mov x2,NBELEMENTS // number of élements
mov x3,#city_name // sort by city name
mov x4,#'A' // alphanumeric
bl shellSort
ldr x0,qAdrTableCities // address table
bl displayTable
100: // standard end of the program
mov x0,0 // return code
mov x8,EXIT // request to exit program
svc 0 // perform the system call
qAdrsZoneConv: .quad sZoneConv
qAdrszCarriageReturn: .quad szCarriageReturn
qAdrsMessResult: .quad sMessResult
qAdrTableCities: .quad TableCities
qAdrszMessSortHab: .quad szMessSortHab
qAdrszMessSortName: .quad szMessSortName
/***************************************************/
/* shell Sort */
/***************************************************/
/* x0 contains the address of table */
/* x1 contains the first element but not use !! */
/* this routine use first element at index zero !!! */
/* x2 contains the number of element */
/* x3 contains the offset of sort zone */
/* x4 contains type of sort zone N = numeric A = alphanumeric */
shellSort:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
stp x6,x7,[sp,-16]! // save registers
stp x8,x9,[sp,-16]! // save registers
stp x10,x11,[sp,-16]! // save registers
stp x12,x13,[sp,-16]! // save registers
mov x8,x3 // save offset area sort
mov x9,x4 // save type sort
mov x7,city_end // element size
sub x12,x2,1 // index last item
mov x11,x12 // init gap = last item
1: // start loop 1
lsr x11,x11,1 // gap = gap / 2
cbz x11,100f // if gap = 0 -> end
mov x3,x11 // init loop indice 1
2: // start loop 2
mul x1,x3,x7 // offset élement
mov x2,NBELEMENTS
mul x2,x7,x2
bl copyElement
add x1,x1,x8 // + offset sort zone
ldr x4,[x0,x1] // load first value
mov x5,x3 // init loop indice 2
3: // start loop 3
cmp x5,x11 // indice < gap
blt 7f // yes -> end loop 2
sub x6,x5,x11 // index = indice - gap
mul x1,x6,x7 // compute offset
add x10,x1,x8 // + offset sort zone
ldr x2,[x0,x10] // load second value
cmp x9,#'A' // sort area alapha ?
beq 4f // yes
cmp x4,x2 // else compare numeric values
bge 7f // highter
b 6f // lower
4: // compare area alphanumeric
mov x10,#0 // counter
5:
ldrb w13,[x4,x10] // byte string 1
ldrb w6,[x2,x10] // byte string 2
cmp w13,w6
bgt 7f
blt 6f

cmp w13,#0 // end string 1
beq 7f // end comparaison
add x10,x10,#1 // else add 1 in counter
b 5b // and loop

6:
mul x2,x5,x7 // offset élement
bl copyElement // copy element x1 to element x2
sub x5,x5,x11 // indice = indice - gap
b 3b // and loop
7:
mov x1,NBELEMENTS
mul x1,x7,x1
mul x2,x7,x5
bl copyElement
add x3,x3,1 // increment indice 1
cmp x3,x12 // end ?
ble 2b // no -> loop 2
b 1b // yes loop for new gap
100: // end function
ldp x12,x13,[sp],16 // restaur 2 registers
ldp x10,x11,[sp],16 // restaur 2 registers
ldp x8,x9,[sp],16 // restaur 2 registers
ldp x6,x7,[sp],16 // restaur 2 registers
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30

/******************************************************************/
/* copy table element */
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 offset destination element */
copyElement:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
mov x3,0
add x1,x1,x0
add x2,x2,x0
1:
ldrb w4,[x1,x3]
strb w4,[x2,x3]
add x3,x3,1
cmp x3,city_end
blt 1b
100:
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/******************************************************************/
/* Display table elements */
/******************************************************************/
/* x0 contains the address of table */
displayTable:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
stp x6,x7,[sp,-16]! // save registers
mov x2,x0 // table address
mov x3,0
mov x6,city_end
1: // loop display table
mul x4,x3,x6
add x4,x4,city_name
ldr x1,[x2,x4]
ldr x0,qAdrsMessResult
bl strInsertAtCharInc // put name in message
mov x5,x0 // save address of new message
mul x4,x3,x6
add x4,x4,city_habitants // and load value
ldr x0,[x2,x4]
ldr x1,qAdrsZoneConv // display value
bl conversion10 // call function
mov x0,x5
ldr x1,qAdrsZoneConv
bl strInsertAtCharInc // insert result at @ character
bl affichageMess // display message
add x3,x3,1
cmp x3,#NBELEMENTS - 1
ble 1b
ldr x0,qAdrszCarriageReturn
bl affichageMess
100:
ldp x6,x7,[sp],16 // restaur 2 registers
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
<pre>
Sort table for number of habitants :
Name : L'Albère number habitants : 83
Name : Taillet number habitants : 115
Name : Vivés number habitants : 174
Name : Les Cluses number habitants : 251
Name : Le Perthus number habitants : 586
Name : Reynes number habitants : 1354
Name : Saint Jean Pla de Corts number habitants : 2153
Name : Maureillas number habitants : 2596
Name : Le Boulou number habitants : 5554
Name : Ceret number habitants : 7705

Sort table for name of city :
Name : Ceret number habitants : 7705
Name : L'Albère number habitants : 83
Name : Le Boulou number habitants : 5554
Name : Le Perthus number habitants : 586
Name : Les Cluses number habitants : 251
Name : Maureillas number habitants : 2596
Name : Reynes number habitants : 1354
Name : Saint Jean Pla de Corts number habitants : 2153
Name : Taillet number habitants : 115
Name : Vivés number habitants : 174
</pre>


=={{header|ACL2}}==
=={{header|ACL2}}==
<lang Lisp>(defun insert-by-key (o os key)
<syntaxhighlight lang="lisp">(defun insert-by-key (o os key)
(cond ((endp os) (list o))
(cond ((endp os) (list o))
((< (cdr (assoc key o))
((< (cdr (assoc key o))
Line 51: Line 385:
(weight . 15)
(weight . 15)
(value . 60)))
(value . 60)))
'value)</lang>
'value)</syntaxhighlight>


Output:
Output:
Line 69: Line 403:
(WEIGHT . 153)
(WEIGHT . 153)
(VALUE . 200)))</pre>
(VALUE . 200)))</pre>

=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
DEFINE PAIR_SIZE="4"
DEFINE PAIR_COUNT="1"

TYPE Pair=[PTR name,value]

BYTE ARRAY pairs(100)
BYTE count=[0]

PTR FUNC GetItemAddr(INT index)
PTR addr

addr=pairs+index*PAIR_SIZE
RETURN (addr)

PROC PrintArray()
INT i
Pair POINTER p

Put('[)
FOR i=0 TO count-1
DO
IF i>0 THEN Put(' ) FI
p=GetItemAddr(i)
PrintF("(%S,%S)",p.name,p.value)
OD
Put(']) PutE()
RETURN

PROC Append(CHAR ARRAY n,v)
Pair POINTER dst

dst=GetItemAddr(count)
dst.name=n
dst.value=v
count==+1
RETURN

PROC InitData()
Append("Warsaw","Poland")
Append("Prague","Czech Republic")
Append("London","United Kingdom")
Append("Paris","France")
Append("Madrit","Spain")
Append("Berlin","Germany")
Append("Rome","Italy")
Append("Moscow","Russia")
Append("Budapest","Hungary")
RETURN

PROC Sort()
INT i,j,minpos
CHAR ARRAY tmp
Pair POINTER p1,p2

FOR i=0 TO count-2
DO
minpos=i
FOR j=i+1 TO count-1
DO
p1=GetItemAddr(minpos)
p2=GetItemAddr(j)
IF SCompare(p1.name,p2.name)>0 THEN
minpos=j
FI
OD
IF minpos#i THEN
p1=GetItemAddr(minpos)
p2=GetItemAddr(i)
tmp=p1.name p1.name=p2.name p2.name=tmp
tmp=p1.value p1.value=p2.value p2.value=tmp
FI
OD
RETURN

PROC Main()
InitData()
PrintE("Array before sort:")
PrintArray() PutE()
Sort()
PrintE("Array after sort:")
PrintArray()
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Sort_an_array_of_composite_structures.png Screenshot from Atari 8-bit computer]
<pre>
Array before sort:
[(Warsaw,Poland) (Prague,Czech Republic) (London,United Kingdom) (Paris,France) (Madrit,Spain) (Berlin,Germany) (Rome,Italy) (Moscow,Russia) (Budapest,Hungary)]

Array after sort:
[(Berlin,Germany) (Budapest,Hungary) (London,United Kingdom) (Madrit,Spain) (Moscow,Russia) (Paris,France) (Prague,Czech Republic) (Rome,Italy) (Warsaw,Poland)]
</pre>


=={{header|Ada}}==
=={{header|Ada}}==
[[Ada 2005]] defines 2 standard subprograms for sorting arrays - 1 for constrained arrays and 1 for unconstrained arrays. Below is a example of using the unconstrained version.
[[Ada 2005]] defines 2 standard subprograms for sorting arrays - 1 for constrained arrays and 1 for unconstrained arrays. Below is a example of using the unconstrained version.
<lang ada>with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
<syntaxhighlight lang="ada">with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Text_IO; use Ada.Text_IO;


Line 112: Line 542:
Put_Line (Data (I));
Put_Line (Data (I));
end loop;
end loop;
end Demo_Array_Sort;</lang>
end Demo_Array_Sort;</syntaxhighlight>
Result:
Result:
<pre>
<pre>
Line 123: Line 553:
</pre>
</pre>
[[Ada 2005]] also provides ordered containers, so no explicit call is required. Here is an example of an ordered set:
[[Ada 2005]] also provides ordered containers, so no explicit call is required. Here is an example of an ordered set:
<lang ada>with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
<syntaxhighlight lang="ada">with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Text_IO; use Ada.Text_IO;


Line 164: Line 594:
Data.Insert (New_Item => (Name => +"David", Value => +"19"));
Data.Insert (New_Item => (Name => +"David", Value => +"19"));
Data.Iterate (Put_Line'Access);
Data.Iterate (Put_Line'Access);
end Sort_Composites;</lang>
end Sort_Composites;</syntaxhighlight>
Result:
Result:
<pre>
<pre>
Line 175: Line 605:
</pre>
</pre>
There is no standard sort function for [[Ada 95]]. The example below implements a simple bubble sort.
There is no standard sort function for [[Ada 95]]. The example below implements a simple bubble sort.
<lang ada>with Ada.Text_Io;
<syntaxhighlight lang="ada">with Ada.Text_Io;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;


Line 228: Line 658:
Sort_Name(My_Pairs);
Sort_Name(My_Pairs);
Print(My_Pairs);
Print(My_Pairs);
end Sort_Composite;</lang>
end Sort_Composite;</syntaxhighlight>


=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
Line 236: Line 666:
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
<!-- {{does not work with|ELLA ALGOL 68|Any (with appropriate job cards AND formatted transput statements removed) - tested with release 1.8.8d.fc9.i386 - ELLA has no FORMATted transput}} -->
<!-- {{does not work with|ELLA ALGOL 68|Any (with appropriate job cards AND formatted transput statements removed) - tested with release 1.8.8d.fc9.i386 - ELLA has no FORMATted transput}} -->
<lang algol68>MODE SORTSTRUCT = PERSON;
<syntaxhighlight lang="algol68">MODE SORTSTRUCT = PERSON;
OP < = (PERSON a,b)BOOL: age OF a < age OF b;
OP < = (PERSON a,b)BOOL: age OF a < age OF b;
PR READ "prelude/sort.a68" PR;
PR READ "prelude/sort.a68" PR;
Line 244: Line 674:


[]SORTSTRUCT person = (("joe", 120), ("foo", 31), ("bar", 51));
[]SORTSTRUCT person = (("joe", 120), ("foo", 31), ("bar", 51));
printf((person repr, shell sort(person), $l$))</lang>
printf((person repr, shell sort(person), $l$))</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 255: Line 685:
macOS Yosemite onwards, for import of Foundation framework
macOS Yosemite onwards, for import of Foundation framework


<lang AppleScript>use framework "Foundation"
<syntaxhighlight lang="applescript">use framework "Foundation"


----- SORTING COMPOSITE STRUCTURES (BY MULTIPLE KEYS) ------
----- SORTING COMPOSITE STRUCTURES (BY MULTIPLE KEYS) ------
Line 326: Line 756:
end script
end script
end if
end if
end mReturn</lang>
end mReturn</syntaxhighlight>
{{Out}}
{{Out}}
<pre>{{pop:24.2, city:"Sao Paulo "}, {pop:24.2, city:"Shanghai "}, {pop:23.5, city:"Karachi "}, {pop:21.5, city:"Beijing "}, {pop:17.0, city:"Dhaka "}, {pop:16.8, city:"Delhi "}, {pop:16.1, city:"Lagos "}}</pre>
<pre>{{pop:24.2, city:"Sao Paulo "}, {pop:24.2, city:"Shanghai "}, {pop:23.5, city:"Karachi "}, {pop:21.5, city:"Beijing "}, {pop:17.0, city:"Dhaka "}, {pop:16.8, city:"Delhi "}, {pop:16.1, city:"Lagos "}}</pre>
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi}}
<syntaxhighlight lang="arm assembly">


/* ARM assembly Raspberry PI */
=={{header|Arturo}}==
/* program compositeSort.s */


/* REMARK 1 : this program use routines in a include file
<lang arturo>arr: #(#{ name: "Joe" , value: 3 };
see task Include a file language arm assembly
#{ name: "Bill" , value: 4 };
for the routine affichageMess conversion10
#{ name: "Alice" , value: 20 };
see at end of this program the instruction include */
#{ name: "Harry" , value: 3 })
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes */
/************************************/
.include "../constantes.inc"


/*******************************************/
sortBy! arr -> &.value
/* Structures */
/********************************************/
/* city structure */
.struct 0
city_name: @
.struct city_name + 4
city_habitants: @
.struct city_habitants + 4
city_end:
/*********************************/
/* Initialized data */
/*********************************/
.data
sMessResult: .asciz "Name : @ number habitants : @ \n"
szMessSortHab: .asciz "Sort table for number of habitants :\n"
szMessSortName: .asciz "Sort table for name of city :\n"
szCarriageReturn: .asciz "\n"
// cities name
szCeret: .asciz "Ceret"
szMaureillas: .asciz "Maureillas"
szTaillet: .asciz "Taillet"
szReynes: .asciz "Reynes"
szVives: .asciz "Vivés"
szBoulou: .asciz "Le Boulou"
szSaintJean: .asciz "Saint Jean Pla de Corts"
szCluses: .asciz "Les Cluses"
szAlbere: .asciz "L'Albère"
szPerthus: .asciz "Le Perthus"
.align 4


TableCities:
print arr</lang>
.int szCluses @ address name string
.int 251 @ number of habitants
.int szCeret
.int 7705
.int szMaureillas
.int 2596
.int szBoulou
.int 5554
.int szSaintJean
.int 2153
.int szAlbere
.int 83
.int szVives
.int 174
.int szTaillet
.int 115
.int szPerthus
.int 586
.int szReynes
.int 1354
.equ NBELEMENTS, (. - TableCities) / city_end
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
sZoneConv: .skip 24
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: @ entry of program
ldr r0,iAdrszMessSortHab
bl affichageMess

ldr r0,iAdrTableCities @ address city table
mov r1,#0 @ not use in routine
mov r2,#NBELEMENTS @ number of élements
mov r3,#city_habitants @ sort by number habitants
mov r4,#'N' @ Alphanumeric
bl shellSort
ldr r0,iAdrTableCities @ address number table
bl displayTable
ldr r0,iAdrszMessSortName
bl affichageMess
ldr r0,iAdrTableCities @ address city table
mov r1,#0 @ not use in routine
mov r2,#NBELEMENTS @ number of élements
mov r3,#city_name @ sort by name
mov r4,#'A' @ Alphanumeric
bl shellSort
ldr r0,iAdrTableCities @ address number table
bl displayTable

100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc #0 @ perform the system call
iAdrszCarriageReturn: .int szCarriageReturn
iAdrsMessResult: .int sMessResult
iAdrTableCities: .int TableCities
iAdrszMessSortHab: .int szMessSortHab
iAdrszMessSortName: .int szMessSortName
/***************************************************/
/* shell Sort */
/***************************************************/

/* r0 contains the address of table */
/* r1 contains the first element but not use !! */
/* this routine use first element at index zero !!! */
/* r2 contains the number of element */
/* r3 contains the offset of sort zone */
/* r4 contains type of sort zone N = numeric A = alphanumeric */
shellSort:
push {r0-r12,lr} @ save registers
sub sp,#city_end @ reserve area on stack
mov fp,sp @ frame pointer = stack
mov r8,r3 @ save offser area sort
mov r9,r4 @ save type sort
mov r7,#city_end @ element size
//vidregtit debut
sub r12,r2,#1 @ index last item
mov r6,r12 @ init gap = last item
1: @ start loop 1
lsrs r6,#1 @ gap = gap / 2
beq 100f @ if gap = 0 -> end
mov r3,r6 @ init loop indice 1
2: @ start loop 2
mul r1,r3,r7 @ offset élement
mov r2,fp @ save on stack
bl saveElement
add r1,r8 @ + offset sort zone
ldr r4,[r0,r1] @ load first value
mov r5,r3 @ init loop indice 2
3: @ start loop 3
cmp r5,r6 @ indice < gap
blt 8f @ yes -> end loop 2
sub r10,r5,r6 @ index = indice - gap
mul r1,r10,r7 @ offset élement
add r10,r1,r8 @ + offset sort zone
ldr r2,[r0,r10] @ load second value
push {r3,r5} @ save registrars because not enought register
cmp r9,#'A' @ sort area alapha ?
beq 4f @ yes
cmp r4,r2 @ else compare numeric values
bge 7f @ highter
b 6f @ lower
4: @ compare area alphanumeric
mov r10,#0 @ counter
5:
ldrb r3,[r4,r10] @ byte string 1
ldrb r5,[r2,r10] @ byte string 2
cmp r3,r5
bgt 7f
blt 6f

cmp r3,#0 @ end string 1
beq 7f @ ens comparaison
add r10,r10,#1 @ else add 1 in counter
b 5b @ and loop
6:
pop {r3,r5} @ restaur registers
mul r2,r5,r7 @ offset élement
bl copyElement @ copy element r1 to element r2
sub r5,r6 @ indice = indice - gap
b 3b @ and loop
7:
pop {r3,r5}
8: @ end loop 3
mul r1,r5,r7 @ offset destination élement
mov r2,fp @ restaur element in table
bl restaurElement
add r3,#1 @ increment indice 1
cmp r3,r12 @ end ?
ble 2b @ no -> loop 2
b 1b @ yes loop for new gap
100: @ end function
add sp,#city_end
pop {r0-r12,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* copy table element */
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 offset destination element */
copyElement:
push {r0-r4,lr} @ save registers
//vidregtit copy
mov r3,#0
add r1,r0
add r2,r0
1:
ldrb r4,[r1,r3]
strb r4,[r2,r3]
add r3,#1
cmp r3,#city_end
blt 1b
100:
pop {r0-r4,lr}
bx lr
/******************************************************************/
/* save element */
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 address destination */
saveElement:
push {r0-r4,lr} @ save registers
mov r3,#0
add r1,r0
1:
ldrb r4,[r1,r3]
strb r4,[r2,r3]
add r3,#1
cmp r3,#city_end
blt 1b
100:
pop {r0-r4,lr}
bx lr
/******************************************************************/
/* restaur element */
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset destination element */
/* r2 address origine */
restaurElement:
push {r0-r4,lr} @ save registers
mov r3,#0
add r1,r0
1:
ldrb r4,[r2,r3]
strb r4,[r1,r3]
add r3,#1
cmp r3,#city_end
blt 1b
100:
pop {r0-r4,lr}
bx lr
/******************************************************************/
/* Display table elements */
/******************************************************************/
/* r0 contains the address of table */
displayTable:
push {r0-r6,lr} @ save registers
mov r2,r0 @ table address
mov r3,#0
mov r6,#city_end
1: @ loop display table
mul r4,r3,r6
add r4,#city_name
ldr r1,[r2,r4]
ldr r0,iAdrsMessResult
bl strInsertAtCharInc @ put name in message
mov r5,r0 @ save address of new message
mul r4,r3,r6
add r4,#city_habitants @ and load value
ldr r0,[r2,r4]
ldr r1,iAdrsZoneConv
bl conversion10 @ call decimal conversion
mov r0,r5
ldr r1,iAdrsZoneConv @ insert conversion in message
bl strInsertAtCharInc
bl affichageMess @ display message
add r3,#1
cmp r3,#NBELEMENTS - 1
ble 1b
ldr r0,iAdrszCarriageReturn
bl affichageMess
100:
pop {r0-r6,lr}
bx lr
iAdrsZoneConv: .int sZoneConv

/***************************************************/
/* ROUTINES INCLUDE */
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
<pre>
Sort table for number of habitants :
Name : L'Albère number habitants : 83
Name : Taillet number habitants : 115
Name : Vivés number habitants : 174
Name : Les Cluses number habitants : 251
Name : Le Perthus number habitants : 586
Name : Reynes number habitants : 1354
Name : Saint Jean Pla de Corts number habitants : 2153
Name : Maureillas number habitants : 2596
Name : Le Boulou number habitants : 5554
Name : Ceret number habitants : 7705

Sort table for name of city :
Name : Ceret number habitants : 7705
Name : L'Albère number habitants : 83
Name : Le Boulou number habitants : 5554
Name : Le Perthus number habitants : 586
Name : Les Cluses number habitants : 251
Name : Maureillas number habitants : 2596
Name : Reynes number habitants : 1354
Name : Saint Jean Pla de Corts number habitants : 2153
Name : Taillet number habitants : 115
Name : Vivés number habitants : 174
</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="arturo">people: [
["joe" 120]
["foo" 31]
["bar" 51]
]

print arrange people 'x -> x\0</syntaxhighlight>


{{out}}
{{out}}


<pre>[bar 51] [foo 31] [joe 120]</pre>
<pre>#(#{ name: "Joe", value: 3 } #{ name: "Harry", value: 3 } #{ name: "Bill", value: 4 } #{ name: "Alice", value: 20 })</pre>

=={{header|ATS}}==

<syntaxhighlight lang="ats">#include "share/atspre_staload.hats"

typedef pair =
'{
name = string,
value = string
}

fn
sort_pairs {n : int}
(pairs : &array (pair, n) >> _,
n : size_t n)
:<!wrt> void =
let
implement
array_quicksort$cmp<pair> (x, y) =
strcmp (x.name, y.name)
in
array_quicksort<pair> (pairs, n)
end

implement
main0 () =
let
val pairs_list : list (pair, 9) =
$list
('{name = "Warsaw", value = "Poland"},
'{name = "Prague", value = "Czech Republic"},
'{name = "London", value = "United Kingdom"},
'{name = "Paris", value = "France"},
'{name = "Madrid", value = "Spain"},
'{name = "Berlin", value = "Germany"},
'{name = "Rome", value = "Italy"},
'{name = "Moscow", value = "Russia"},
'{name = "Budapest", value = "Hungary"})

var pairs_array : @[pair][9]
val () = array_initize_list<pair> (pairs_array, 9, pairs_list)

val () = sort_pairs (pairs_array, i2sz 9)

var i : [i : nat | i <= 9] int i
in
for (i := 0; i <> 9; i := succ i)
println! (pairs_array[i].name, " -> ", pairs_array[i].value)
end</syntaxhighlight>

{{out}}
<pre>$ patscc -DATS_MEMALLOC_GCBDW -O3 sort_composite_structures.dats -lgc && ./a.out
Berlin -> Germany
Budapest -> Hungary
London -> United Kingdom
Madrid -> Spain
Moscow -> Russia
Paris -> France
Prague -> Czech Republic
Rome -> Italy
Warsaw -> Poland</pre>


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
built ListView Gui, contains a table sorting function which can be used for this.
built ListView Gui, contains a table sorting function which can be used for this.
<lang AutoHotkey>start:
<syntaxhighlight lang="autohotkey">start:
Gui, Add, ListView, r20 w200, 1|2
Gui, Add, ListView, r20 w200, 1|2
data =
data =
Line 370: Line 1,178:


GuiClose:
GuiClose:
ExitApp</lang>
ExitApp</syntaxhighlight>


=={{header|AWK}}==
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f SORT_AN_ARRAY_OF_COMPOSITE_STRUCTURES.AWK
# syntax: GAWK -f SORT_AN_ARRAY_OF_COMPOSITE_STRUCTURES.AWK
BEGIN {
BEGIN {
Line 408: Line 1,216:
printf("\n")
printf("\n")
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 419: Line 1,227:
First, we construct a list-of-maps and assign it to variable baz. Next, we sort baz by key "foo" and assign it to variable bop. Finally, we lookup "foo" in each map in list bop and display the resulting list of numbers - they are in sorted order.
First, we construct a list-of-maps and assign it to variable baz. Next, we sort baz by key "foo" and assign it to variable bop. Finally, we lookup "foo" in each map in list bop and display the resulting list of numbers - they are in sorted order.


<lang babel>babel> baz ([map "foo" 3 "bar" 17] [map "foo" 4 "bar" 18] [map "foo" 5 "bar" 19] [map "foo" 0 "bar" 20]) <
<syntaxhighlight lang="babel">babel> baz ([map "foo" 3 "bar" 17] [map "foo" 4 "bar" 18] [map "foo" 5 "bar" 19] [map "foo" 0 "bar" 20]) <
babel> bop baz { <- "foo" lumap ! -> "foo" lumap ! lt? } lssort ! <
babel> bop baz { <- "foo" lumap ! -> "foo" lumap ! lt? } lssort ! <
babel> bop {"foo" lumap !} over ! lsnum !
babel> bop {"foo" lumap !} over ! lsnum !
( 0 3 4 5 )</lang>
( 0 3 4 5 )</syntaxhighlight>


The same technique works for any list of data-objects you may have. User-code can expect to have the top two elements of the stack set to be the two objects to be compared. Simply access the relevant field in each object, and then perform a comparison. For example, here is a list of pairs sorted by first element:
The same technique works for any list of data-objects you may have. User-code can expect to have the top two elements of the stack set to be the two objects to be compared. Simply access the relevant field in each object, and then perform a comparison. For example, here is a list of pairs sorted by first element:


<lang babel>babel> 20 lsrange ! {1 randlf 2 rem} lssort ! 2 group ! --> this creates a shuffled list of pairs
<syntaxhighlight 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
babel> dup {lsnum !} ... --> display the shuffled list, pair-by-pair
( 11 10 )
( 11 10 )
Line 449: Line 1,257:
( 15 13 )
( 15 13 )
( 17 3 )
( 17 3 )
( 18 9 )</lang>
( 18 9 )</syntaxhighlight>


The gpsort utility performs this kind of comparison "automagically" by leveraging the ordering of Babel's underlying data-structure. Using the shuffled list from the example above:
The gpsort utility performs this kind of comparison "automagically" by leveraging the ordering of Babel's underlying data-structure. Using the shuffled list from the example above:


<lang babel>babel> gpsort !
<syntaxhighlight lang="babel">babel> gpsort !
babel> dup {lsnum !} ...
babel> dup {lsnum !} ...
( 0 2 )
( 0 2 )
Line 464: Line 1,272:
( 15 13 )
( 15 13 )
( 17 3 )
( 17 3 )
( 18 9 )</lang>
( 18 9 )</syntaxhighlight>


Note that gpsort will not work for the case where you want to sort on the second element of a list of pairs. But it will work for performing a canonical sort on numbers, arrays of numbers, lists of numbers, lists of lists, lists of arrays, arrays of lists, and so on. You should not use gpsort with strings; use lexsort or strsort instead. Here's an example of sorting a mixture of pairs and triples using gpsort:
Note that gpsort will not work for the case where you want to sort on the second element of a list of pairs. But it will work for performing a canonical sort on numbers, arrays of numbers, lists of numbers, lists of lists, lists of arrays, arrays of lists, and so on. You should not use gpsort with strings; use lexsort or strsort instead. Here's an example of sorting a mixture of pairs and triples using gpsort:


<lang babel>babel> dup {lsnum !} ... --> display the shuffled list of pairs and triples
<syntaxhighlight lang="babel">babel> dup {lsnum !} ... --> display the shuffled list of pairs and triples
( 7 2 )
( 7 2 )
( 6 4 )
( 6 4 )
Line 490: Line 1,298:
( 8 2 3 )
( 8 2 3 )
( 9 6 10 )
( 9 6 10 )
( 11 13 7 )</lang>
( 11 13 7 )</syntaxhighlight>


=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
Uses the supplied SORTSALIB library.
Uses the supplied SORTSALIB library.
<lang bbcbasic> INSTALL @lib$+"SORTSALIB"
<syntaxhighlight lang="bbcbasic"> INSTALL @lib$+"SORTSALIB"
sort% = FN_sortSAinit(0,0)
sort% = FN_sortSAinit(0,0)
Line 513: Line 1,321:
FOR i% = 1 TO DIM(array{()}, 1)
FOR i% = 1 TO DIM(array{()}, 1)
PRINT array{(i%)}.name$, array{(i%)}.number%
PRINT array{(i%)}.name$, array{(i%)}.number%
NEXT</lang>
NEXT</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 530: Line 1,338:
=={{header|Bracmat}}==
=={{header|Bracmat}}==
The easiest way to sort an array of elements in Bracmat is to handle it as a sum of terms. A sum, when evaluated, is automatically sorted.
The easiest way to sort an array of elements in Bracmat is to handle it as a sum of terms. A sum, when evaluated, is automatically sorted.
<lang bracmat>( (tab=("C++",1979)+(Ada,1983)+(Ruby,1995)+(Eiffel,1985))
<syntaxhighlight lang="bracmat">( (tab=("C++",1979)+(Ada,1983)+(Ruby,1995)+(Eiffel,1985))
& out$"unsorted array:"
& out$"unsorted array:"
& lst$tab
& lst$tab
Line 536: Line 1,344:
& out$"But tab is still unsorted:"
& out$"But tab is still unsorted:"
& lst$tab
& lst$tab
);</lang>
);</syntaxhighlight>


Output:
Output:
Line 553: Line 1,361:


When evaluating <code>!tab</code>, the expression bound to the variable name <code>tab</code> is sorted, but the unevaluated expression is still bound to <code>tab</code>. An assignment binds the sorted expression to <code>tab</code>:
When evaluating <code>!tab</code>, the expression bound to the variable name <code>tab</code> is sorted, but the unevaluated expression is still bound to <code>tab</code>. An assignment binds the sorted expression to <code>tab</code>:
<lang bracmat>( !tab:?tab
<syntaxhighlight lang="bracmat">( !tab:?tab
& out$"Now tab is sorted:"
& out$"Now tab is sorted:"
& lst$tab
& lst$tab
);</lang>
);</syntaxhighlight>


Output:
Output:
Line 565: Line 1,373:


To sort an array that is not a sum expression, we can convert it to a sum:
To sort an array that is not a sum expression, we can convert it to a sum:
<lang bracmat>( ((name.map),(weight.9),(value.150))
<syntaxhighlight lang="bracmat">( ((name.map),(weight.9),(value.150))
((name.compass),(weight.13),(value.35))
((name.compass),(weight.13),(value.35))
((name.water),(weight.153),(value.200))
((name.water),(weight.153),(value.200))
Line 585: Line 1,393:
& out$("Array after sorting (descending order):" !array \n)
& out$("Array after sorting (descending order):" !array \n)
& out$("Array after sorting (ascending order):" reverse$!array \n)
& out$("Array after sorting (ascending order):" reverse$!array \n)
);</lang>
);</syntaxhighlight>


Output:
Output:
Line 612: Line 1,420:


Bracmat has a left to right sorting order. If an array must be sorted on another field than the first field, that other field has to be made the first field. After sorting, the fields can take their original positions.
Bracmat has a left to right sorting order. If an array must be sorted on another field than the first field, that other field has to be made the first field. After sorting, the fields can take their original positions.
<lang bracmat>( (Joe,5531)
<syntaxhighlight lang="bracmat">( (Joe,5531)
(Adam,2341)
(Adam,2341)
(Bernie,122)
(Bernie,122)
Line 633: Line 1,441:
\n
\n
)
)
);</lang>
);</syntaxhighlight>


Output:
Output:
Line 653: Line 1,461:
=={{header|C}}==
=={{header|C}}==
Using qsort, from the standard library.
Using qsort, from the standard library.
<syntaxhighlight lang="c">
<lang c>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
Line 750: Line 1,558:


return 0;
return 0;
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre> This is the order in which many strings should be sorted.
<pre> This is the order in which many strings should be sorted.
Line 758: Line 1,566:
{{works with|C sharp|C#|3+}}
{{works with|C sharp|C#|3+}}


<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
Line 784: Line 1,592:
Console.WriteLine("{0,-11}{1}", e.Name, e.Value);
Console.WriteLine("{0,-11}{1}", e.Name, e.Value);
}
}
}</lang>
}</syntaxhighlight>


Output:
Output:
Line 798: Line 1,606:
Uses C++11. Compile with
Uses C++11. Compile with
g++ -std=c++11 sort.cpp
g++ -std=c++11 sort.cpp
<lang cpp>#include <algorithm>
<syntaxhighlight lang="cpp">#include <algorithm>
#include <iostream>
#include <iostream>
#include <string>
#include <string>
Line 825: Line 1,633:
std::cout << "{" << e.name << ", " << e.value << "}\n";
std::cout << "{" << e.name << ", " << e.value << "}\n";
}
}
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 843: Line 1,651:
Clojure has a ''sort-by'' function which takes a ''keyfn'' and a ''coll''. It returns a sorted sequence of the items in ''coll'', where the sort order is determined by comparing ''(keyfn item)''.
Clojure has a ''sort-by'' function which takes a ''keyfn'' and a ''coll''. It returns a sorted sequence of the items in ''coll'', where the sort order is determined by comparing ''(keyfn item)''.


<lang clojure>
<syntaxhighlight lang="clojure">
;; Gathered with Google Squared
;; Gathered with Google Squared
(def *langs* [["Clojure" 2007] ["Common Lisp" 1984] ["Java" 1995] ["Haskell" 1990]
(def *langs* [["Clojure" 2007] ["Common Lisp" 1984] ["Java" 1995] ["Haskell" 1990]
Line 851: Line 1,659:


(["Lisp" 1958] ["Scheme" 1975] ["Common Lisp" 1984] ["Haskell" 1990] ["Java" 1995] ["Clojure" 2007])
(["Lisp" 1958] ["Scheme" 1975] ["Common Lisp" 1984] ["Haskell" 1990] ["Java" 1995] ["Clojure" 2007])
</syntaxhighlight>
</lang>


You can also supply a comparator (using ''compare'' or a sibling of ''<''). A comparator can be used with the regular ''sort'' function or the ''sort-by'' function. In the latter case, the comparator will be used on ''(keyfn item)'' instead of ''item''.
You can also supply a comparator (using ''compare'' or a sibling of ''<''). A comparator can be used with the regular ''sort'' function or the ''sort-by'' function. In the latter case, the comparator will be used on ''(keyfn item)'' instead of ''item''.


<lang clojure>
<syntaxhighlight lang="clojure">
user> (sort #(compare (second %1) (second %2)) *langs*) ; using a comparator
user> (sort #(compare (second %1) (second %2)) *langs*) ; using a comparator


Line 863: Line 1,671:


(["Clojure" 2007] ["Java" 1995] ["Haskell" 1990] ["Common Lisp" 1984] ["Scheme" 1975] ["Lisp" 1958])
(["Clojure" 2007] ["Java" 1995] ["Haskell" 1990] ["Common Lisp" 1984] ["Scheme" 1975] ["Lisp" 1958])
</syntaxhighlight>
</lang>


Read the docstring of ''sort'' and ''sort-by'' for more info.
Read the docstring of ''sort'' and ''sort-by'' for more info.
Line 872: Line 1,680:
Let's define a composite structure of U.S. states and average test scores.
Let's define a composite structure of U.S. states and average test scores.


<lang lisp>CL-USER> (defparameter *test-scores* '(("texas" 68.9) ("ohio" 87.8) ("california" 76.2) ("new york" 88.2)) )
<syntaxhighlight lang="lisp">CL-USER> (defparameter *test-scores* '(("texas" 68.9) ("ohio" 87.8) ("california" 76.2) ("new york" 88.2)) )
*TEST-SCORES*</lang>
*TEST-SCORES*</syntaxhighlight>
We can sort by the state name by supplying a one-argument key function that is called by the ''sort'' function to determine the value to compare. In this case, the function is ''first'' will retrieve the state name:
We can sort by the state name by supplying a one-argument key function that is called by the ''sort'' function to determine the value to compare. In this case, the function is ''first'' will retrieve the state name:


<lang lisp>CL-USER> (sort (copy-list *test-scores*) #'string-lessp :key #'first)
<syntaxhighlight lang="lisp">CL-USER> (sort (copy-list *test-scores*) #'string-lessp :key #'first)
(("california" 76.2) ("new york" 88.2) ("ohio" 87.8) ("texas" 68.9))</lang>
(("california" 76.2) ("new york" 88.2) ("ohio" 87.8) ("texas" 68.9))</syntaxhighlight>


we can also sort by the test scores by supplying a different key function that return the test score instead:
we can also sort by the test scores by supplying a different key function that return the test score instead:


<lang lisp>CL-USER> (sort (copy-list *test-scores*) #'< :key #'second)
<syntaxhighlight lang="lisp">CL-USER> (sort (copy-list *test-scores*) #'< :key #'second)
(("texas" 68.9) ("california" 76.2) ("ohio" 87.8) ("new york" 88.2))</lang>
(("texas" 68.9) ("california" 76.2) ("ohio" 87.8) ("new york" 88.2))</syntaxhighlight>


=={{header|D}}==
=={{header|D}}==
<lang d>import std.stdio, std.algorithm;
<syntaxhighlight lang="d">import std.stdio, std.algorithm;


struct Pair { string name, value; }
struct Pair { string name, value; }
Line 898: Line 1,706:


pairs.schwartzSort!q{ a.name }.writeln;
pairs.schwartzSort!q{ a.name }.writeln;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[Pair("Adam", "2341"), Pair("Bernie", "122"), Pair("David", "19"), Pair("Joe", "5531"), Pair("Walter", "1234")]</pre>
<pre>[Pair("Adam", "2341"), Pair("Bernie", "122"), Pair("David", "19"), Pair("Joe", "5531"), Pair("Walter", "1234")]</pre>


=={{header|Delphi}}==
=={{header|Delphi}}==
<lang Delphi>program SortCompositeStructures;
<syntaxhighlight lang="delphi">program SortCompositeStructures;


{$APPTYPE CONSOLE}
{$APPTYPE CONSOLE}
Line 935: Line 1,743:
Result := CompareText(Left.Name, Right.Name);
Result := CompareText(Left.Name, Right.Name);
end));
end));
end.</lang>
end.</syntaxhighlight>


=={{header|E}}==
=={{header|E}}==


<lang e>def compareBy(keyfn) { # This ought to be in the standard library
<syntaxhighlight lang="e">def compareBy(keyfn) { # This ought to be in the standard library
return def comparer(a, b) {
return def comparer(a, b) {
return keyfn(a).op__cmp(keyfn(b))
return keyfn(a).op__cmp(keyfn(b))
Line 952: Line 1,760:
]
]


println(x.sort(compareBy(fn [name,_] { name })))</lang>
println(x.sort(compareBy(fn [name,_] { name })))</syntaxhighlight>


=={{header|EchoLisp}}==
=={{header|EchoLisp}}==
<lang scheme>
<syntaxhighlight lang="scheme">
;; sorting (name value) by name - Ignoring case
;; sorting (name value) by name - Ignoring case
(define (name a) (first a))
(define (name a) (first a))
Line 967: Line 1,775:
→ (("albert" 33) ("Antoinette" 42) ("elvis" 666) ("Simone" 44) ("😃" 1000) ("😎" -42))
→ (("albert" 33) ("Antoinette" 42) ("elvis" 666) ("Simone" 44) ("😃" 1000) ("😎" -42))


</syntaxhighlight>
</lang>


=={{header|Elena}}==
=={{header|Elena}}==
ELENA 5.0 :
ELENA 6.x :
<lang elena>import system'routines;
<syntaxhighlight lang="elena">import system'routines;
import extensions;
import extensions;
Line 984: Line 1,792:
KeyValue.new("Germanium", 72.64r)};
KeyValue.new("Germanium", 72.64r)};
var sorted := elements.sort:(former,later => former.Key < later.Key );
var sorted := elements.sort::(former,later => former.Key < later.Key );
sorted.forEach:(element)
sorted.forEach::(element)
{
{
console.printLine(element.Key," - ",element)
console.printLine(element.Key," - ",element)
}
}
}</lang>
}</syntaxhighlight>


=={{header|Elixir}}==
=={{header|Elixir}}==
<lang elixir>defmodule Person do
<syntaxhighlight lang="elixir">defmodule Person do
defstruct name: "", value: 0
defstruct name: "", value: 0
end
end
Line 1,004: Line 1,812:
Enum.sort(list) |> Enum.each(fn x -> IO.inspect x end)
Enum.sort(list) |> Enum.each(fn x -> IO.inspect x end)
IO.puts ""
IO.puts ""
Enum.sort_by(list, &(&1.value)) |> Enum.each(&IO.inspect &1)</lang>
Enum.sort_by(list, &(&1.value)) |> Enum.each(&IO.inspect &1)</syntaxhighlight>


{{out}}
{{out}}
Line 1,021: Line 1,829:
=={{header|Erlang}}==
=={{header|Erlang}}==
Any Erlang type can be compared to any Erlang type. As such, nothing special needs to be done:
Any Erlang type can be compared to any Erlang type. As such, nothing special needs to be done:
<lang Erlang>1> lists:sort([{{2006,2007},"Ducks"},
<syntaxhighlight lang="erlang">1> lists:sort([{{2006,2007},"Ducks"},
{{2000,2001},"Avalanche"},
{{2000,2001},"Avalanche"},
{{2002,2003},"Devils"},
{{2002,2003},"Devils"},
Line 1,040: Line 1,848:
{{2006,2007},"Ducks"},
{{2006,2007},"Ducks"},
{{2007,2008},"Red Wings"},
{{2007,2008},"Red Wings"},
{{2008,2009},"Penguins"}]</lang>
{{2008,2009},"Penguins"}]</syntaxhighlight>


It is also possible to sort with custom functions, in this case by the team's name:
It is also possible to sort with custom functions, in this case by the team's name:
<lang Erlang>2> F = fun({_,X},{_,Y}) -> X < Y end.
<syntaxhighlight lang="erlang">2> F = fun({_,X},{_,Y}) -> X < Y end.
#Fun<erl_eval.12.113037538>
#Fun<erl_eval.12.113037538>
3> lists:usort(F, [{{2006,2007},"Ducks"},
3> lists:usort(F, [{{2006,2007},"Ducks"},
Line 1,064: Line 1,872:
{{2008,2009},"Penguins"},
{{2008,2009},"Penguins"},
{{2007,2008},"Red Wings"},
{{2007,2008},"Red Wings"},
{{2001,2002},"Red Wings"}]</lang>
{{2001,2002},"Red Wings"}]</syntaxhighlight>


=={{header|Euphoria}}==
=={{header|Euphoria}}==
<lang euphoria>include sort.e
<syntaxhighlight lang="euphoria">include sort.e
include misc.e
include misc.e


Line 1,081: Line 1,889:
{ "cherry", "red" } }
{ "cherry", "red" } }


pretty_print(1,custom_sort(routine_id("compare_names"),s),{2})</lang>
pretty_print(1,custom_sort(routine_id("compare_names"),s),{2})</syntaxhighlight>


Output:
Output:
Line 1,105: Line 1,913:
=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
F# has <code>sortBy</code> functions that work on collection types for this purpose. An example using an array of pairs:
F# has <code>sortBy</code> functions that work on collection types for this purpose. An example using an array of pairs:
<lang fsharp>let persons = [| ("Joe", 120); ("foo", 31); ("bar", 51) |]
<syntaxhighlight lang="fsharp">let persons = [| ("Joe", 120); ("foo", 31); ("bar", 51) |]
Array.sortInPlaceBy fst persons
Array.sortInPlaceBy fst persons
printfn "%A" persons</lang>
printfn "%A" persons</syntaxhighlight>
Output:
Output:
Line 1,113: Line 1,921:


An example using a list of records:
An example using a list of records:
<lang fsharp>type Person = { name:string; id:int }
<syntaxhighlight lang="fsharp">type Person = { name:string; id:int }
let persons2 = [{name="Joe"; id=120}; {name="foo"; id=31}; {name="bar"; id=51}]
let persons2 = [{name="Joe"; id=120}; {name="foo"; id=31}; {name="bar"; id=51}]
let sorted = List.sortBy (fun p -> p.id) persons2
let sorted = List.sortBy (fun p -> p.id) persons2
for p in sorted do printfn "%A" p</lang>
for p in sorted do printfn "%A" p</syntaxhighlight>


Output:
Output:
Line 1,129: Line 1,937:
This is essentially the same as [[Sorting Using a Custom Comparator]].
This is essentially the same as [[Sorting Using a Custom Comparator]].


<lang factor>TUPLE: example-pair name value ;
<syntaxhighlight lang="factor">TUPLE: example-pair name value ;


: sort-by-name ( seq -- seq' ) [ [ name>> ] compare ] sort ;</lang>
: sort-by-name ( seq -- seq' ) [ [ name>> ] compare ] sort ;</syntaxhighlight>


( scratchpad ) { T{ example-pair f "omega" "a" } T{ example-pair f "gamma" "q" } T{ example-pair f "alpha" "z" } } sort-by-name .
( scratchpad ) { T{ example-pair f "omega" "a" } T{ example-pair f "gamma" "q" } T{ example-pair f "alpha" "z" } } sort-by-name .
Line 1,144: Line 1,952:
Any object can be sorted as needed by passing an appropriate block to the 'sort' method.
Any object can be sorted as needed by passing an appropriate block to the 'sort' method.


<lang fantom>
<syntaxhighlight lang="fantom">
class Pair // create a composite structure
class Pair // create a composite structure
{
{
Line 1,177: Line 1,985:
}
}
}
}
</syntaxhighlight>
</lang>


=={{header|Fortran}}==
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
{{works with|Fortran|90 and later}}
Standard Fortran has no built-in sort function although some compilers add them. The following example uses an insertion sort.
Standard Fortran has no built-in sort function although some compilers add them. The following example uses an insertion sort.
<lang fortran>PROGRAM EXAMPLE
<syntaxhighlight lang="fortran">PROGRAM EXAMPLE
IMPLICIT NONE
IMPLICIT NONE


Line 1,216: Line 2,024:
WRITE (*,"(2A6)") rcc
WRITE (*,"(2A6)") rcc


END PROGRAM EXAMPLE</lang>
END PROGRAM EXAMPLE</syntaxhighlight>
Output
Output
Black 0
Black 0
Line 1,230: Line 2,038:


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>' FB 1.05.0 Win64
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64


Type Pair
Type Pair
Line 1,282: Line 2,090:
Print
Print
Print "Press any key to quit"
Print "Press any key to quit"
Sleep</lang>
Sleep</syntaxhighlight>


{{out}}
{{out}}
Line 1,298: Line 2,106:
[snow, white]
[snow, white]
</pre>
</pre>

=={{header|Frink}}==
Frink's <CODE>lexicalCompare[a, b, language]</CODE> function can sort strings in a lexicographically correct way for many human languages by specifying a language specifier like "da" for Danish. This allows sort routines to magically work correctly for many human languages.
<syntaxhighlight lang="frink">class Pair
{
var name
var value
new[name is string, value is string] :=
{
this.name = name
this.value = value
}
}

a = [new Pair["one", "1"], new Pair["two", "2"], new Pair["three", "3"]]
sort[a, {|a,b| lexicalCompare[a.name, b.name]}]
</syntaxhighlight>

{{out}}
<pre>[Pair
{
name = one
value = 1
}
, Pair
{
name = three
value = 3
}
, Pair
{
name = two
value = 2
}
]
</pre>

=={{header|Fōrmulæ}}==

{{FormulaeEntry|page=https://formulae.org/?script=examples/Sort_an_array_of_composite_structures}}

'''Solution'''

In the following example, it is assumed that the key is the first element of each pair.

[[File:Fōrmulæ - Sort an array of composite structures 01.png]]

[[File:Fōrmulæ - Sort an array of composite structures 02.png]]


=={{header|Go}}==
=={{header|Go}}==
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 1,328: Line 2,185:
fmt.Printf("%5s: %s\n", p.name, p.value)
fmt.Printf("%5s: %s\n", p.name, p.value)
}
}
}</lang>
}</syntaxhighlight>


=={{header|Groovy}}==
=={{header|Groovy}}==
<lang groovy>class Holiday {
<syntaxhighlight lang="groovy">class Holiday {
def date
def date
def name
def name
Line 1,355: Line 2,212:


holidays.sort { x, y -> x.date <=> y.date }
holidays.sort { x, y -> x.date <=> y.date }
holidays.each { println it }</lang>
holidays.each { println it }</syntaxhighlight>


Output:
Output:
Line 1,374: Line 2,231:


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang haskell>import Data.List
<syntaxhighlight lang="haskell">import Data.List
import Data.Function (on)
import Data.Function (on)


Line 1,399: Line 2,256:
mapM_ print $ sort people
mapM_ print $ sort people
putStrLn []
putStrLn []
mapM_ print $ sortBy (on compare pVal) people</lang>
mapM_ print $ sortBy (on compare pVal) people</syntaxhighlight>


{{Out}}
{{Out}}
Line 1,416: Line 2,273:
To sort a list of triples by the third element, for example:
To sort a list of triples by the third element, for example:


<lang haskell>import Data.Ord (comparing)
<syntaxhighlight lang="haskell">import Data.Ord (comparing)
import Data.List (sortBy)
import Data.List (sortBy)


Line 1,427: Line 2,284:


main :: IO ()
main :: IO ()
main = mapM_ print $ sortBy (comparing (\(_, _, y) -> y)) xs</lang>
main = mapM_ print $ sortBy (comparing (\(_, _, y) -> y)) xs</syntaxhighlight>
{{Out}}
{{Out}}
<pre>("Maurice","Wilkes",1913)
<pre>("Maurice","Wilkes",1913)
Line 1,438: Line 2,295:
=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==
The built-in procedure sortf will sort a list by the field in a records.
The built-in procedure sortf will sort a list by the field in a records.
<lang Icon>record star(name,HIP)
<syntaxhighlight lang="icon">record star(name,HIP)


procedure main()
procedure main()
Line 1,449: Line 2,306:
write("Some Orion stars by HIP#")
write("Some Orion stars by HIP#")
every write( (x := !sortf(Ori,2)).name, " HIP ",x.HIP)
every write( (x := !sortf(Ori,2)).name, " HIP ",x.HIP)
end</lang>
end</syntaxhighlight>


Sample output:<pre>Some Orion stars by HIP#
Sample output:<pre>Some Orion stars by HIP#
Line 1,460: Line 2,317:
The function<tt> /: </tt>sorts anything (its left argument) based on the keys supplied in its right argument. For example:
The function<tt> /: </tt>sorts anything (its left argument) based on the keys supplied in its right argument. For example:


<lang j> names =: ;: 'Perlis Wilkes Hamming Minsky Wilkinson McCarthy'
<syntaxhighlight lang="j"> names =: ;: 'Perlis Wilkes Hamming Minsky Wilkinson McCarthy'
values=: ;: 'Alan Maurice Richard Marvin James John'
values=: ;: 'Alan Maurice Richard Marvin James John'
pairs =: values ,. names
pairs =: values ,. names
Line 1,476: Line 2,333:
+-------+---------+
+-------+---------+
|James |Wilkinson|
|James |Wilkinson|
+-------+---------+</lang>
+-------+---------+</syntaxhighlight>


Alternatively, J's cross operator will use the same values for both the left and right arguments for /: but, in this case, /:~ is not desirable because that would have us sorting on the values (the first column) and only using the second column for equal names (none of which appear, here).
Alternatively, J's cross operator will use the same values for both the left and right arguments for /: but, in this case, /:~ is not desirable because that would have us sorting on the values (the first column) and only using the second column for equal names (none of which appear, here).


=={{header|Java}}==
=={{header|Java}}==
<lang java>import java.util.Arrays;
<syntaxhighlight lang="java">import java.util.Arrays;
import java.util.Comparator;
import java.util.Comparator;


Line 1,514: Line 2,371:
});
});
}
}
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>00-01 Avalanche
<pre>00-01 Avalanche
Line 1,529: Line 2,386:
In Java 8, we can write the above using a lambda:
In Java 8, we can write the above using a lambda:
{{works with|Java|8+}}
{{works with|Java|8+}}
<lang java> public static void sortByName(Pair[] pairs) {
<syntaxhighlight lang="java"> public static void sortByName(Pair[] pairs) {
Arrays.sort(pairs, (p1, p2) -> p1.name.compareTo(p2.name));
Arrays.sort(pairs, (p1, p2) -> p1.name.compareTo(p2.name));
}</lang>
}</syntaxhighlight>


We can further use <code>Comparator.comparing()</code> to construct the comparator from a "key" function:
We can further use <code>Comparator.comparing()</code> to construct the comparator from a "key" function:
{{works with|Java|8+}}
{{works with|Java|8+}}
<lang java> public static void sortByName(Pair[] pairs) {
<syntaxhighlight lang="java"> public static void sortByName(Pair[] pairs) {
Arrays.sort(pairs, Comparator.comparing(p -> p.name));
Arrays.sort(pairs, Comparator.comparing(p -> p.name));
}</lang>
}</syntaxhighlight>


=={{header|JavaScript}}==
=={{header|JavaScript}}==
===ES5===
===ES5===
<lang javascript>var arr = [
<syntaxhighlight lang="javascript">var arr = [
{id: 3, value: "foo"},
{id: 3, value: "foo"},
{id: 2, value: "bar"},
{id: 2, value: "bar"},
Line 1,549: Line 2,406:
];
];
arr = arr.sort(function(a, b) {return a.id - b.id}); // Sort with comparator checking the id.
arr = arr.sort(function(a, b) {return a.id - b.id}); // Sort with comparator checking the id.
</syntaxhighlight>
</lang>


===ES6===
===ES6===


<lang JavaScript>(() => {
<syntaxhighlight lang="javascript">(() => {
'use strict';
'use strict';


Line 1,614: Line 2,471:
.sort(on(flip(compare), name))
.sort(on(flip(compare), name))
});
});
})();</lang>
})();</syntaxhighlight>


{{Out}}
{{Out}}
Line 1,742: Line 2,599:
=={{header|jq}}==
=={{header|jq}}==
In this section we will focus on JSON objects since the task description mentions keys. As an example, we will use this array:
In this section we will focus on JSON objects since the task description mentions keys. As an example, we will use this array:
<lang jq>def example:
<syntaxhighlight lang="jq">def example:
[
[
{"name": "Joe", "value": 3},
{"name": "Joe", "value": 3},
Line 1,748: Line 2,605:
{"name": "Alice", "value": 20},
{"name": "Alice", "value": 20},
{"name": "Harry", "value": 3}
{"name": "Harry", "value": 3}
];</lang>
];</syntaxhighlight>
====Using sort_by builtin ====
====Using sort_by builtin ====
jq's sort_by builtin can be used to sort by the value of a given key (whether or not it is a string), so we will first use that.
jq's sort_by builtin can be used to sort by the value of a given key (whether or not it is a string), so we will first use that.
<lang jq># To sort the array:
<syntaxhighlight lang="jq"># To sort the array:
# example | sort_by(.name)
# example | sort_by(.name)


# To abbreviate the results, we will just show the names after sorting:
# To abbreviate the results, we will just show the names after sorting:


example | sort_by(.name) | map( .name )</lang>
example | sort_by(.name) | map( .name )</syntaxhighlight>
{{Out}}
{{Out}}
$ jq -n -c -f Sort_an_array_of_composite_structures.jq
$ jq -n -c -f Sort_an_array_of_composite_structures.jq
Line 1,763: Line 2,620:
====Using quicksort(cmp)====
====Using quicksort(cmp)====
sort_by(f) can easily be implemented using quicksort(cmp) as defined at [[Sorting_Using_a_Custom_Comparator#jq]] as follows:
sort_by(f) can easily be implemented using quicksort(cmp) as defined at [[Sorting_Using_a_Custom_Comparator#jq]] as follows:
<lang jq>def quicksort_by(f): quicksort( (.[0]|f) <= (.[1]|f) );</lang>
<syntaxhighlight lang="jq">def quicksort_by(f): quicksort( (.[0]|f) <= (.[1]|f) );</syntaxhighlight>
'''Example''':
'''Example''':
<lang jq>example | quicksort_by(.name) | map( .name )</lang>
<syntaxhighlight lang="jq">example | quicksort_by(.name) | map( .name )</syntaxhighlight>
{{Out}}
{{Out}}
As above.
As above.
Line 1,772: Line 2,629:
{{works with|Julia|0.6}}
{{works with|Julia|0.6}}


<lang julia>lst = Pair[Pair("gold", "shiny"),
<syntaxhighlight lang="julia">lst = Pair[Pair("gold", "shiny"),
Pair("neon", "inert"),
Pair("neon", "inert"),
Pair("sulphur", "yellow"),
Pair("sulphur", "yellow"),
Line 1,788: Line 2,645:
println("\nThe list, sorted by name: \n - ", join(lst, "\n - "))
println("\nThe list, sorted by name: \n - ", join(lst, "\n - "))
sort!(lst; by=last)
sort!(lst; by=last)
println("\nThe list, sorted by value: \n - ", join(lst, "\n - "))</lang>
println("\nThe list, sorted by value: \n - ", join(lst, "\n - "))</syntaxhighlight>


{{out}}
{{out}}
Line 1,831: Line 2,688:


=={{header|Kotlin}}==
=={{header|Kotlin}}==
<lang scala>// version 1.1
<syntaxhighlight lang="scala">// version 1.1


data class Employee(val name: String, var category: String) : Comparable<Employee> {
data class Employee(val name: String, var category: String) : Comparable<Employee> {
Line 1,848: Line 2,705:
employees.sort()
employees.sort()
for ((name, category) in employees) println("${name.padEnd(6)} : $category")
for ((name, category) in employees) println("${name.padEnd(6)} : $category")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,861: Line 2,718:


=={{header|Lambdatalk}}==
=={{header|Lambdatalk}}==
<lang scheme>
<syntaxhighlight lang="scheme">
{def H.sort
{def H.sort
{def H.sort.i
{def H.sort.i
Line 1,910: Line 2,767:
David Bernie Walter Adam Joe
David Bernie Walter Adam Joe
19 122 1234 2341 5531
19 122 1234 2341 5531
</syntaxhighlight>
</lang>


=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==
Line 1,916: Line 2,773:
<br>
<br>
The method used here to simulate a compound structure can only hold pairs of terms, since LB arrays ar 1D or 2D. More complicated associated arrays could be stored in delimiter-separated string arrays.
The method used here to simulate a compound structure can only hold pairs of terms, since LB arrays ar 1D or 2D. More complicated associated arrays could be stored in delimiter-separated string arrays.
<syntaxhighlight lang="lb">
<lang lb>
N =20
N =20
dim IntArray$( N, 2)
dim IntArray$( N, 2)
Line 1,935: Line 2,792:
print IntArray$( i, 1), IntArray$( i, 2)
print IntArray$( i, 1), IntArray$( i, 2)
next i
next i
</syntaxhighlight>
</lang>


=={{header|Lua}}==
=={{header|Lua}}==
<lang lua>function sorting( a, b )
<syntaxhighlight lang="lua">function sorting( a, b )
return a[1] < b[1]
return a[1] < b[1]
end
end
Line 1,947: Line 2,804:
for _, v in ipairs( tab ) do
for _, v in ipairs( tab ) do
print( unpack(v) )
print( unpack(v) )
end</lang>
end</syntaxhighlight>


=={{header|M2000 Interpreter}}==
=={{header|M2000 Interpreter}}==
Line 1,956: Line 2,813:
Checkit3 same as CheckIt3 except values are groups, which now have only a x as value, but we can add more.
Checkit3 same as CheckIt3 except values are groups, which now have only a x as value, but we can add more.


<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module CheckIt {
Module CheckIt {
Flush ' empty stack of values
Flush ' empty stack of values
Line 2,052: Line 2,909:
}
}
Checkit3
Checkit3
</syntaxhighlight>
</lang>


{{Out}}
{{Out}}
Line 2,072: Line 2,929:
</pre>
</pre>


=={{header|Mathematica}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<lang Mathematica>events = {{"2009-12-25", "Christmas Day"}, {"2009-04-22",
<syntaxhighlight lang="mathematica">events = {{"2009-12-25", "Christmas Day"}, {"2009-04-22",
"Earth Day"}, {"2009-09-07", "Labor Day"}, {"2009-07-04",
"Earth Day"}, {"2009-09-07", "Labor Day"}, {"2009-07-04",
"Independence Day"}, {"2009-10-31", "Halloween"}, {"2009-05-25",
"Independence Day"}, {"2009-10-31", "Halloween"}, {"2009-05-25",
Line 2,085: Line 2,942:
name = 2;
name = 2;
SortBy[events, #[[name]] &] // Grid
SortBy[events, #[[name]] &] // Grid
SortBy[events, #[[date]] &] // Grid</lang>
SortBy[events, #[[date]] &] // Grid</syntaxhighlight>
gives back:
gives back:
<lang Mathematica>2009-12-25 Christmas Day
<syntaxhighlight lang="mathematica">2009-12-25 Christmas Day
2009-04-22 Earth Day
2009-04-22 Earth Day
2009-10-31 Halloween
2009-10-31 Halloween
Line 2,116: Line 2,973:
2009-11-26 Thanksgiving
2009-11-26 Thanksgiving
2009-12-25 Christmas Day
2009-12-25 Christmas Day
2009-12-31 New Year's Eve</lang>
2009-12-31 New Year's Eve</syntaxhighlight>


=={{header|MAXScript}}==
=={{header|MAXScript}}==
<lang maxscript>fn keyCmp comp1 comp2 =
<syntaxhighlight lang="maxscript">fn keyCmp comp1 comp2 =
(
(
case of
case of
Line 2,131: Line 2,988:
people = #(#("joe", 39), #("dave", 37), #("bob", 42))
people = #(#("joe", 39), #("dave", 37), #("bob", 42))
qsort people keyCmp
qsort people keyCmp
print people</lang>
print people</syntaxhighlight>


=={{header|NetRexx}}==
=={{header|NetRexx}}==
<lang NetRexx>/* NetRexx */
<syntaxhighlight lang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
options replace format comments java crossref symbols nobinary


Line 2,188: Line 3,045:
else signal IllegalArgumentException('Arguments must be of type PairBean')
else signal IllegalArgumentException('Arguments must be of type PairBean')
return cRes
return cRes
</syntaxhighlight>
</lang>
'''Output:'''
'''Output:'''
<pre>
<pre>
Line 2,196: Line 3,053:


=={{header|Nim}}==
=={{header|Nim}}==
<lang nim>import algorithm, future
<syntaxhighlight lang="nim">import algorithm, sugar


var people = @{"joe": 120, "foo": 31, "bar": 51}
var people = @{"joe": 120, "foo": 31, "bar": 51}
sort(people, (x,y) => cmp(x[0], y[0]))
sort(people, (x,y) => cmp(x[0], y[0]))
echo people</lang>
echo people</syntaxhighlight>
{{Out}}
Output:
<pre>@[(Field0: bar, Field1: 51), (Field0: foo, Field1: 31), (Field0: joe, Field1: 120)]</pre>
<pre>@[("bar", 51), ("foo", 31), ("joe", 120)]</pre>


=={{header|Objeck}}==
=={{header|Objeck}}==
<lang objeck>
<syntaxhighlight lang="objeck">
use Collection;
use Collection;


Line 2,250: Line 3,107:
}
}
}
}
</syntaxhighlight>
</lang>


<pre>
<pre>
Line 2,262: Line 3,119:


=={{header|Objective-C}}==
=={{header|Objective-C}}==
<lang objc>@interface Pair : NSObject {
<syntaxhighlight lang="objc">@interface Pair : NSObject {
NSString *name;
NSString *name;
NSString *value;
NSString *value;
Line 2,316: Line 3,173:


return 0;
return 0;
}</lang>
}</syntaxhighlight>


=={{header|OCaml}}==
=={{header|OCaml}}==
<lang ocaml># let people = [("Joe", 12); ("Bob", 8); ("Alice", 9); ("Harry", 2)];;
<syntaxhighlight lang="ocaml"># let people = [("Joe", 12); ("Bob", 8); ("Alice", 9); ("Harry", 2)];;
val people : (string * int) list =
val people : (string * int) list =
[("Joe", 12); ("Bob", 8); ("Alice", 9); ("Harry", 2)]
[("Joe", 12); ("Bob", 8); ("Alice", 9); ("Harry", 2)]
# let sortedPeopleByVal = List.sort (fun (_, v1) (_, v2) -> compare v1 v2) people;;
# let sortedPeopleByVal = List.sort (fun (_, v1) (_, v2) -> compare v1 v2) people;;
val sortedPeopleByVal : (string * int) list =
val sortedPeopleByVal : (string * int) list =
[("Harry", 2); ("Bob", 8); ("Alice", 9); ("Joe", 12)]</lang>
[("Harry", 2); ("Bob", 8); ("Alice", 9); ("Joe", 12)]</syntaxhighlight>


=={{header|Oforth}}==
=={{header|Oforth}}==


<lang Oforth>[["Joe",5531], ["Adam",2341], ["Bernie",122], ["David",19]] sortBy(#first) println</lang>
<syntaxhighlight lang="oforth">[["Joe",5531], ["Adam",2341], ["Bernie",122], ["David",19]] sortBy(#first) println</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
[[Adam, 2341], [Bernie, 122], [David, 19], [Joe, 5531]]
[[Adam, 2341], [Bernie, 122], [David, 19], [Joe, 5531]]
</pre>

=={{header|Ol}}==
<syntaxhighlight lang="scheme">
(import (scheme char))

(define (comp a b)
(string-ci<? (a 'name #f) (b 'name #f)))

(for-each print
(sort comp (list
{ 'name "David"
'value "Manager" }
{ 'name "Alice"
'value "Sales" }
{ 'name "Joanna"
'value "Director" }
{ 'name "Henry"
'value "Admin" }
{ 'name "Tim"
'value "Sales" }
{ 'name "Juan"
'value "Admin" })))
</syntaxhighlight>
{{Out}}
<pre>
#ff((name . Alice) (value . Sales))
#ff((name . David) (value . Manager))
#ff((name . Henry) (value . Admin))
#ff((name . Joanna) (value . Director))
#ff((name . Juan) (value . Admin))
#ff((name . Tim) (value . Sales))
</pre>
</pre>


=={{header|ooRexx}}==
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
<lang ooRexx>
a = .array~new
a = .array~new


Line 2,391: Line 3,280:
-- perform the comparison on the names
-- perform the comparison on the names
return -left~name~compareTo(right~name)
return -left~name~compareTo(right~name)
</syntaxhighlight>
</lang>
Output:
Output:
<pre>
<pre>
Line 2,420: Line 3,309:


=={{header|Oz}}==
=={{header|Oz}}==
<lang oz>declare
<syntaxhighlight lang="oz">declare
People = [person(name:joe value:3)
People = [person(name:joe value:3)
person(name:bill value:4)
person(name:bill value:4)
Line 2,432: Line 3,321:
}
}
in
in
{ForAll SortedPeople Show}</lang>
{ForAll SortedPeople Show}</syntaxhighlight>


=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
The flag "2" means that lexicographic sorting is to be used; the "1" means that the array is to be sorted using the first element of each constituent vector.
The flag "2" means that lexicographic sorting is to be used; the "1" means that the array is to be sorted using the first element of each constituent vector.
<lang parigp>vecsort([["name", "value"],["name2", "value2"]], 1, 2)</lang>
<syntaxhighlight lang="parigp">vecsort([["name", "value"],["name2", "value2"]], 1, 2)</syntaxhighlight>


=={{header|Pascal}}==
=={{header|Pascal}}==
Line 2,443: Line 3,332:
=={{header|Perl}}==
=={{header|Perl}}==
Sort by name using cmp to compare strings:
Sort by name using cmp to compare strings:
<lang perl>@people = (['joe', 120], ['foo', 31], ['bar', 51]);
<syntaxhighlight lang="perl">@people = (['joe', 120], ['foo', 31], ['bar', 51]);
@people = sort { $a->[0] cmp $b->[0] } @people;</lang>
@people = sort { $a->[0] cmp $b->[0] } @people;</syntaxhighlight>


Sort by number using <=> to compare numbers:
Sort by number using <=> to compare numbers:
<lang perl>@people = (['joe', 120], ['foo', 31], ['bar', 51]);
<syntaxhighlight lang="perl">@people = (['joe', 120], ['foo', 31], ['bar', 51]);
@people = sort { $a->[1] <=> $b->[1] } @people;</lang>
@people = sort { $a->[1] <=> $b->[1] } @people;</syntaxhighlight>


=={{header|Phix}}==
=={{header|Phix}}==
{{libheader|Phix/basics}}
The standard sort compares the first element, then 2nd, 3rd, etc. A custom_sort or sort_columns can be used to sort by other elements.<br>
The standard sort compares the first element, then 2nd, 3rd, etc. A custom_sort or sort_columns can be used to sort by other elements.<br>
Elements can be any mix of types, with atoms (ie ints/floats) deemed less than sequences/strings.
Elements can be any mix of types, with atoms (ie ints/floats) deemed less than sequences/strings.
<!--<syntaxhighlight lang="phix">-->
<lang Phix>sequence s = {{"grass","green"},{"snow","white"},{"sky","blue"},{"cherry","red"},{0,1.2},{3.4,-1}}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"grass"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"green"</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">"snow"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"white"</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">"sky"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"blue"</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">"cherry"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"red"</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1.2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3.4</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}}</span>

?sort(s)
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
function compare_col2(sequence a, b) return compare(a[2],b[2]) end function
<span style="color: #008080;">function</span> <span style="color: #000000;">compare_col2</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: #008080;">return</span> <span style="color: #7060A8;">compare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
?custom_sort(routine_id("compare_col2"),s)
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">custom_sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">compare_col2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
?sort_columns(s,{2}) -- 0.8.0+, same result as above w/o needing an explicit comparison routine</lang>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">sort_columns</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">})</span> <span style="color: #000080;font-style:italic;">-- 0.8.0+, same result as above w/o needing an explicit comparison routine</span>
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 2,465: Line 3,357:
{{3.4,-1},{0,1.2},{"sky","blue"},{"grass","green"},{"cherry","red"},{"snow","white"}}
{{3.4,-1},{0,1.2},{"sky","blue"},{"grass","green"},{"cherry","red"},{"snow","white"}}
</pre>
</pre>



=={{header|Phixmonti}}==
=={{header|Phixmonti}}==
<lang Phixmonti>include ..\Utilitys.pmt
<syntaxhighlight lang="phixmonti">include ..\Utilitys.pmt


def minverse
def minverse
Line 2,482: Line 3,373:


/# sorted by second component #/
/# sorted by second component #/
f map sort f map print</lang>
f map sort f map print</syntaxhighlight>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
By default, the [http://software-lab.de/doc/refS.html#sort sort] function in
By default, the [http://software-lab.de/doc/refS.html#sort sort] function in
PicoLisp returns an ascending list (of any type)
PicoLisp returns an ascending list (of any type)
<lang PicoLisp>: (sort '(("def" 456) ("abc" 789) ("ghi" 123)))
<syntaxhighlight lang="picolisp">: (sort '(("def" 456) ("abc" 789) ("ghi" 123)))
-> (("abc" 789) ("def" 456) ("ghi" 123))</lang>
-> (("abc" 789) ("def" 456) ("ghi" 123))</syntaxhighlight>
To sort by a certain sub-element, the function
To sort by a certain sub-element, the function
[http://software-lab.de/doc/refB.html#by by] can be used. For example, to
[http://software-lab.de/doc/refB.html#by by] can be used. For example, to
sort by the first element
sort by the first element
<lang PicoLisp>: (by car sort '(("def" 456) ("abc" 789) ("ghi" 123)))
<syntaxhighlight lang="picolisp">: (by car sort '(("def" 456) ("abc" 789) ("ghi" 123)))
-> (("abc" 789) ("def" 456) ("ghi" 123))</lang>
-> (("abc" 789) ("def" 456) ("ghi" 123))</syntaxhighlight>
or by the second element
or by the second element
<lang PicoLisp>: (by cadr sort '(("def" 456) ("abc" 789) ("ghi" 123)))
<syntaxhighlight lang="picolisp">: (by cadr sort '(("def" 456) ("abc" 789) ("ghi" 123)))
-> (("ghi" 123) ("def" 456) ("abc" 789))</lang>
-> (("ghi" 123) ("def" 456) ("abc" 789))</syntaxhighlight>


=={{header|PowerShell}}==
=={{header|PowerShell}}==
Line 2,502: Line 3,393:
{{works with|PowerShell|4.0}}
{{works with|PowerShell|4.0}}


<syntaxhighlight lang="powershell">
<lang PowerShell>
$list = @{
$list = @{
"def" = "one"
"def" = "one"
Line 2,512: Line 3,403:
}
}
$list.GetEnumerator() | sort {-($PSItem.Name).length}, Name
$list.GetEnumerator() | sort {-($PSItem.Name).length}, Name
</lang>
</syntaxhighlight>
<b>Output:</b>
<b>Output:</b>
<pre>
<pre>
Line 2,533: Line 3,424:


'''Example'''
'''Example'''
<lang PureBasic>Structure MyPair ; Define a structured data type
<syntaxhighlight lang="purebasic">Structure MyPair ; Define a structured data type
Name$
Name$
Value.i
Value.i
Line 2,565: Line 3,456:
; Wait for user...
; Wait for user...
PrintN(#CRLF$+"Press ENTER to exit"):Input()
PrintN(#CRLF$+"Press ENTER to exit"):Input()
EndIf</lang>
EndIf</syntaxhighlight>


'''Outputs
'''Outputs
Line 2,581: Line 3,472:
Recent versions of Python provide the ''sorted()'' built-in that works on any iterable.
Recent versions of Python provide the ''sorted()'' built-in that works on any iterable.


<lang python>people = [('joe', 120), ('foo', 31), ('bar', 51)]
<syntaxhighlight lang="python">people = [('joe', 120), ('foo', 31), ('bar', 51)]
sorted(people)</lang>
sorted(people)</syntaxhighlight>
Which leaves <code>people</code> with the value:
Which leaves <code>people</code> with the value:
<lang python>[('bar', 51), ('foo', 31), ('joe', 120)]</lang>
<syntaxhighlight lang="python">[('bar', 51), ('foo', 31), ('joe', 120)]</syntaxhighlight>


<br>The most Pythonic (and fastest) version is to use itemgetter together with the key parameter to <code>sort</code> resp. <code>sorted</code> to perform the [[wp:Decorate-sort-undecorate|Decorate-sort-undecorate]] pattern:
<br>The most Pythonic (and fastest) version is to use itemgetter together with the key parameter to <code>sort</code> resp. <code>sorted</code> to perform the [[wp:Decorate-sort-undecorate|Decorate-sort-undecorate]] pattern:


<lang python>from operator import itemgetter
<syntaxhighlight lang="python">from operator import itemgetter
people = [(120, 'joe'), (31, 'foo'), (51, 'bar')]
people = [(120, 'joe'), (31, 'foo'), (51, 'bar')]
people.sort(key=itemgetter(1))</lang>
people.sort(key=itemgetter(1))</syntaxhighlight>
Which leaves <code>people</code> with the value:
Which leaves <code>people</code> with the value:
<lang python>[(51, 'bar'), (31, 'foo'), (120, 'joe')]</lang>
<syntaxhighlight lang="python">[(51, 'bar'), (31, 'foo'), (120, 'joe')]</syntaxhighlight>


=={{header|R}}==
=={{header|R}}==
In R, vectors can have names associated with any of its elements. The data is taken from the Common Lisp example.
In R, vectors can have names associated with any of its elements. The data is taken from the Common Lisp example.
<lang R>sortbyname <- function(x, ...) x[order(names(x), ...)]
<syntaxhighlight lang="r">sortbyname <- function(x, ...) x[order(names(x), ...)]
x <- c(texas=68.9, ohio=87.8, california=76.2, "new york"=88.2)
x <- c(texas=68.9, ohio=87.8, california=76.2, "new york"=88.2)
sortbyname(x)</lang>
sortbyname(x)</syntaxhighlight>
california new york ohio texas
california new york ohio texas
76.2 88.2 87.8 68.9
76.2 88.2 87.8 68.9


<lang R>sortbyname(x, decreasing=TRUE)</lang>
<syntaxhighlight lang="r">sortbyname(x, decreasing=TRUE)</syntaxhighlight>
texas ohio new york california
texas ohio new york california
68.9 87.8 88.2 76.2
68.9 87.8 88.2 76.2


=={{header|Racket}}==
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
#lang racket


Line 2,618: Line 3,509:
(sort data string<? #:key (compose1 symbol->string car))
(sort data string<? #:key (compose1 symbol->string car))
;; --> '((Adam 2341) (Bernie 122) (David 19) (Joe 5531) (Walter 1234))
;; --> '((Adam 2341) (Bernie 122) (David 19) (Joe 5531) (Walter 1234))
</syntaxhighlight>
</lang>


=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)
{{Works with|rakudo|2016.05}}
{{Works with|rakudo|2016.05}}
<lang perl6>my class Employee {
<syntaxhighlight lang="raku" line>my class Employee {
has Str $.name;
has Str $.name;
has Rat $.wage;
has Rat $.wage;
Line 2,641: Line 3,532:
say @orderedByName.join(' ');
say @orderedByName.join(' ');
say "Team ordered by wage (ascending order):";
say "Team ordered by wage (ascending order):";
say @orderedByWage.join(' ');</lang>
say @orderedByWage.join(' ');</syntaxhighlight>
this produces the following output:
this produces the following output:
<pre>Team ordered by name (ascending order):
<pre>Team ordered by name (ascending order):
Line 2,652: Line 3,543:
=={{header|REXX}}==
=={{header|REXX}}==
This version sorts the structure by color; &nbsp; as entered (built), &nbsp; the structure is ordered by value (percent).
This version sorts the structure by color; &nbsp; as entered (built), &nbsp; the structure is ordered by value (percent).
<lang rexx>/*REXX program sorts an array of composite structures (which has two classes of data).*/
<syntaxhighlight lang="rexx">/*REXX program sorts an array of composite structures */
#=0 /*number elements in structure (so far)*/
/* (which has two classes of data). */
name='tan' ; value= 0; call add name,value /*tan peanut M&M's are 0% of total*/
x.=0 /*number elements in structure (so far)*/
name='orange'; value=10; call add name,value /*orange " " " 10% " " */
Call add 'tan' , 0 /*tan peanut M&M's are 0% of total*/
name='yellow'; value=20; call add name,value /*yellow " " " 20% " " */
Call add 'orange',10 /*orange " " " 10% " " */
name='green' ; value=20; call add name,value /*green " " " 20% " " */
Call add 'yellow',20 /*yellow " " " 20% " " */
name='red' ; value=20; call add name,value /*red " " " 20% " " */
Call add 'green' ,20 /*green " " " 20% " " */
name='brown' ; value=30; call add name,value /*brown " " " 30% " " */
Call add 'red' ,20 /*red " " " 20% " " */
Call add 'brown' ,30 /*brown " " " 30% " " */
call show 'before sort', #
Call show 'before sort'
say copies('▒', 70)
Say copies('¦', 70)
call xSort #
Call xSort
call show ' after sort', #
call show ' after sort'
exit /*stick a fork in it, we're all done. */
Exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*--------------------------------------------------------------------*/
add: procedure expose # @.; #=#+1 /*bump the number of structure entries.*/
add: Procedure Expose x.
@.#.color=arg(1); @.#.pc=arg(2) /*construct a entry of the structure. */
z=x.0+1 /* bump the number of structure entry */
return
x.z.color=arg(1)
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: procedure expose @.; do j=1 for arg(2) /*2nd arg≡number of structure elements.*/
x.z.pc=arg(2) /* construct an entry of the structure */
x.0=z
say right(arg(1),30) right(@.j.color,9) right(@.j.pc,4)'%'
Return
end /*j*/ /* [↑] display what, name, value. */
/*--------------------------------------------------------------------*/
return
show: Procedure Expose x.
/*──────────────────────────────────────────────────────────────────────────────────────*/
Do i=1 To x.0
xSort: procedure expose @.; parse arg N; h=N
do while h>1; h=h%2
/* display what name value. */
Say right(arg(1),30) right(x.i.color,9) right(x.i.pc,4)'%'
do i=1 for N-h; j=i; k=h+i
End
do while @.k.color<@.j.color /*swap elements.*/
Return
_=@.j.color; @.j.color=@.k.color; @.k.color=_
/*--------------------------------------------------------------------*/
_=@.j.pc; @.j.pc =@.k.pc; @.k.pc =_
xsort: Procedure Expose x.
if h>=j then leave; j=j-h; k=k-h
h=x.0
end /*while @.k.color ···*/
Do While h>1
end /*i*/
h=h%2
end /*while h>1*/
return</lang>
Do i=1 For x.0-h
j=i
k=h+i
Do While x.k.color<x.j.color
_=x.j.color /* swap elements. */
x.j.color=x.k.color
x.k.color=_
_=x.j.pc
x.j.pc=x.k.pc
x.k.pc=_
If h>=j Then
Leave
j=j-h
k=k-h
End
End
End
Return</syntaxhighlight>
'''output''' &nbsp; when using the (internal) default inputs:
'''output''' &nbsp; when using the (internal) default inputs:
<pre>
<pre>
Line 2,704: Line 3,612:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
aList= [:Eight = 8, :Two = 2, :Five = 5, :Nine = 9, :One = 1,
aList= sort([:Eight = 8, :Two = 2, :Five = 5, :Nine = 9, :One = 1,
:Three = 3, :Six = 6, :Seven = 7, :Four = 4, :Ten = 10]
:Three = 3, :Six = 6, :Seven = 7, :Four = 4, :Ten = 10] , 2)
bList = sort(aList,2)
for item in aList
for n = 1 to len(bList)
? item[1] + space(10-len(item[1])) + item[2]
len = len(bList[n][1])
blen = 10-len
see bList[n][1] + space(blen) + bList[n][2] + nl
next
next
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 2,730: Line 3,635:
=={{header|Ruby}}==
=={{header|Ruby}}==


<lang ruby>Person = Struct.new(:name,:value) do
<syntaxhighlight lang="ruby">Person = Struct.new(:name,:value) do
def to_s; "name:#{name}, value:#{value}" end
def to_s; "name:#{name}, value:#{value}" end
end
end
Line 2,740: Line 3,645:
puts list.sort_by{|x|x.name}
puts list.sort_by{|x|x.name}
puts
puts
puts list.sort_by(&:value)</lang>
puts list.sort_by(&:value)</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,755: Line 3,660:


=={{header|Run BASIC}}==
=={{header|Run BASIC}}==
<lang runbasic>sqliteconnect #mem, ":memory:" ' create in memory db
<syntaxhighlight lang="runbasic">sqliteconnect #mem, ":memory:" ' create in memory db
mem$ = "CREATE TABLE people(num integer, name text,city text)"
mem$ = "CREATE TABLE people(num integer, name text,city text)"
#mem execute(mem$)
#mem execute(mem$)
Line 2,771: Line 3,676:
city$ = #row city$()
city$ = #row city$()
print num;" ";name$;" ";city$
print num;" ";name$;" ";city$
WEND</lang><pre>3 Ben Seneca
WEND</syntaxhighlight><pre>3 Ben Seneca
5 Frank Houston
5 Frank Houston
2 Fred Oregon
2 Fred Oregon
Line 2,779: Line 3,684:
=={{header|Rust}}==
=={{header|Rust}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang Rust>use std::cmp::Ordering;
<syntaxhighlight lang="rust">use std::cmp::Ordering;


#[derive(Debug)]
#[derive(Debug)]
Line 2,829: Line 3,734:
println!("{:<6} : {}", e.name, e.category);
println!("{:<6} : {}", e.name, e.category);
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>Alice : Sales
<pre>Alice : Sales
Line 2,839: Line 3,744:


=={{header|Scala}}==
=={{header|Scala}}==
<lang scala>case class Pair(name:String, value:Double)
<syntaxhighlight lang="scala">case class Pair(name:String, value:Double)
val input = Array(Pair("Krypton", 83.798), Pair("Beryllium", 9.012182), Pair("Silicon", 28.0855))
val input = Array(Pair("Krypton", 83.798), Pair("Beryllium", 9.012182), Pair("Silicon", 28.0855))
input.sortBy(_.name) // Array(Pair(Beryllium,9.012182), Pair(Krypton,83.798), Pair(Silicon,28.0855))
input.sortBy(_.name) // Array(Pair(Beryllium,9.012182), Pair(Krypton,83.798), Pair(Silicon,28.0855))
Line 2,845: Line 3,750:
// alternative versions:
// alternative versions:
input.sortBy(struct => (struct.name, struct.value)) // additional sort field (name first, then value)
input.sortBy(struct => (struct.name, struct.value)) // additional sort field (name first, then value)
input.sortWith((a,b) => a.name.compareTo(b.name) < 0) // arbitrary comparison function</lang>
input.sortWith((a,b) => a.name.compareTo(b.name) < 0) // arbitrary comparison function</syntaxhighlight>


=={{header|Seed7}}==
=={{header|Seed7}}==
<lang seed7>$ include "seed7_05.s7i";
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";


const type: pair is new struct
const type: pair is new struct
Line 2,886: Line 3,791:
writeln(aPair);
writeln(aPair);
end for;
end for;
end func;</lang>
end func;</syntaxhighlight>


Output:
Output:
Line 2,898: Line 3,803:


=={{header|Sidef}}==
=={{header|Sidef}}==
<lang ruby># Declare an array of pairs
<syntaxhighlight lang="ruby"># Declare an array of pairs
var people = [['joe', 120], ['foo', 31], ['bar', 51]];
var people = [['joe', 120], ['foo', 31], ['bar', 51]];


Line 2,908: Line 3,813:


# Display the sorted array
# Display the sorted array
say people;</lang>
say people;</syntaxhighlight>


{{out}}
{{out}}
Line 2,914: Line 3,819:


=={{header|Simula}}==
=={{header|Simula}}==
<lang simula>BEGIN
<syntaxhighlight lang="simula">BEGIN


CLASS COMPARABLE;;
CLASS COMPARABLE;;
Line 2,982: Line 3,887:
OUTIMAGE;
OUTIMAGE;
END.</lang>
END.</syntaxhighlight>
{{out}}
{{out}}
<pre>ADAM 2341
<pre>ADAM 2341
Line 2,991: Line 3,896:


=={{header|SQL}}==
=={{header|SQL}}==
We can treat the array of data structures as a table. An <code>order by</code> clause in a query will sort the data.<lang sql>-- setup
We can treat the array of data structures as a table. An <code>order by</code> clause in a query will sort the data.<syntaxhighlight lang="sql">-- setup
create table pairs (name varchar(16), value varchar(16));
create table pairs (name varchar(16), value varchar(16));
insert into pairs values ('Fluffy', 'cat');
insert into pairs values ('Fluffy', 'cat');
Line 2,997: Line 3,902:
insert into pairs values ('Francis', 'fish');
insert into pairs values ('Francis', 'fish');
-- order them by name
-- order them by name
select * from pairs order by name;</lang>
select * from pairs order by name;</syntaxhighlight>
{{out}}
{{out}}
<pre>NAME VALUE
<pre>NAME VALUE
Line 3,007: Line 3,912:
=={{header|Swift}}==
=={{header|Swift}}==


<lang swift>extension Sequence {
<syntaxhighlight lang="swift">extension Sequence {
func sorted<Value>(
func sorted<Value>(
on: KeyPath<Element, Value>,
on: KeyPath<Element, Value>,
Line 3,027: Line 3,932:
let c = Person(name: "charlie", role: "driver")
let c = Person(name: "charlie", role: "driver")


print([c, b, a].sorted(on: \.name, using: <))</lang>
print([c, b, a].sorted(on: \.name, using: <))</syntaxhighlight>


{{out}}
{{out}}
Line 3,035: Line 3,940:
=={{header|Tcl}}==
=={{header|Tcl}}==
Modeling the data structure being sorted as a list (a common Tcl practice):
Modeling the data structure being sorted as a list (a common Tcl practice):
<lang tcl>set people {{joe 120} {foo 31} {bar 51}}
<syntaxhighlight lang="tcl">set people {{joe 120} {foo 31} {bar 51}}
# sort by the first element of each pair
# sort by the first element of each pair
lsort -index 0 $people</lang>
lsort -index 0 $people</syntaxhighlight>


=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==
With this language, everything is a string. My list of pairs is a string where a colon ":" separates "name:value", and a newline separates different pairs. Then I can use <tt>sort -t: -k1,1</tt> to sort the pairs by name.
With this language, everything is a string. My list of pairs is a string where a colon ":" separates "name:value", and a newline separates different pairs. Then I can use <tt>sort -t: -k1,1</tt> to sort the pairs by name.


<lang bash>list="namez:order!
<syntaxhighlight lang="bash">list="namez:order!
name space:in
name space:in
name1:sort
name1:sort
Line 3,069: Line 3,974:


echo "Sorted list:"
echo "Sorted list:"
dumplist</lang>
dumplist</syntaxhighlight>


Output: <pre>Original list:
Output: <pre>Original list:
Line 3,086: Line 3,991:
The built in sort operator, -<, can be parameterized by an
The built in sort operator, -<, can be parameterized by an
anonymous field specification and/or a relational predicate.
anonymous field specification and/or a relational predicate.
<lang Ursala>#import std
<syntaxhighlight lang="ursala">#import std


#cast %sWLW
#cast %sWLW
Line 3,094: Line 3,999:
(
(
-<&l <('z','a'),('x','c'),('y','b')>, # sorted by the left
-<&l <('z','a'),('x','c'),('y','b')>, # sorted by the left
-<&r <('z','a'),('x','c'),('y','b')>) # sorted by the right</lang>
-<&r <('z','a'),('x','c'),('y','b')>) # sorted by the right</syntaxhighlight>
output:
output:
<pre>(
<pre>(
Line 3,102: Line 4,007:
a more verbose example, showing a list of records of a user defined type sorted by a named field:
a more verbose example, showing a list of records of a user defined type sorted by a named field:


<lang Ursala>#import std
<syntaxhighlight lang="ursala">#import std


person :: name %s value %s
person :: name %s value %s
Line 3,115: Line 4,020:
#cast _person%L
#cast _person%L


example = (lleq+ ~name~~)-< people</lang>
example = (lleq+ ~name~~)-< people</syntaxhighlight>
output:
output:
<pre>
<pre>
Line 3,122: Line 4,027:
person[name: 'Marilyn Monroe',value: 'priceless'],
person[name: 'Marilyn Monroe',value: 'priceless'],
person[name: 'Victor Hugo',value: 'millions']></pre>
person[name: 'Victor Hugo',value: 'millions']></pre>

=={{header|Wren}}==
{{libheader|Wren-sort}}
<syntaxhighlight lang="wren">import "./sort" for Cmp, Sort, Comparable

class Pair is Comparable {
construct new (name, value) {
_name = name
_value = value
}

name { _name }
value { _value }

compare(other) { Cmp.string.call(_name, other.name) }

toString { "{%(_name), %(_value)}" }
}

var pairs = [
Pair.new("grass", "green"),
Pair.new("snow", "white"),
Pair.new("sky", "blue"),
Pair.new("cherry", "red")
]

System.print("Before sorting:")
System.print(" " + pairs.join("\n "))
Sort.insertion(pairs)
System.print("\nAfter sorting:")
System.print(" " + pairs.join("\n "))</syntaxhighlight>

{{out}}
<pre>
Before sorting:
{grass, green}
{snow, white}
{sky, blue}
{cherry, red}

After sorting:
{cherry, red}
{grass, green}
{sky, blue}
{snow, white}
</pre>


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>include c:\cxpl\stdlib;
<syntaxhighlight lang="xpl0">include c:\cxpl\stdlib;
char Dict(10,10);
char Dict(10,10);
int Entries;
int Entries;
Line 3,155: Line 4,106:
for I:= 0 to Entries-1 do \show sorted entries
for I:= 0 to Entries-1 do \show sorted entries
[ChOut(0, Dict(I,0)); ChOut(0, ^ ); Text(0, @Dict(I,1)); CrLf(0)];
[ChOut(0, Dict(I,0)); ChOut(0, ^ ); Text(0, @Dict(I,1)); CrLf(0)];
]</lang>
]</syntaxhighlight>


{{out}}
{{out}}
Line 3,167: Line 4,118:
=={{header|zkl}}==
=={{header|zkl}}==
The list of lists way is available or:
The list of lists way is available or:
<lang zkl>class P{var name,value;
<syntaxhighlight lang="zkl">class P{var name,value;
fcn init(nm,val){name,value=vm.arglist}
fcn init(nm,val){name,value=vm.arglist}
fcn __opLT(p){name<p.name} // implementation of P1 < P2
fcn __opLT(p){name<p.name} // implementation of P1 < P2
Line 3,174: Line 4,125:
p:=List(P("sam","a"),P("fred","b"),P("chris","c"));
p:=List(P("sam","a"),P("fred","b"),P("chris","c"));
p.sort();
p.sort();
p.apply("name"); //-->L("chris","fred","sam")</lang>
p.apply("name"); //-->L("chris","fred","sam")</syntaxhighlight>

Latest revision as of 10:46, 8 February 2024

Task
Sort an array of composite structures
You are encouraged to solve this task according to the task description, using any language you may know.

Sort an array of composite structures by a key.


For example, if you define a composite structure that presents a name-value pair (in pseudo-code):

Define structure pair such that: 
   name as a string
   value as a string

and an array of such pairs:

   x: array of pairs

then define a sort routine that sorts the array x by the key name.

This task can always be accomplished with Sorting Using a Custom Comparator.

If your language is not listed here, please see the other article.

11l

Translation of: Kotlin
T Employee
   String name, category

   F (name, category)
      .name = name
      .category = category

V employees = [
   Employee(‘David’, ‘Manager’),
   Employee(‘Alice’, ‘Sales’),
   Employee(‘Joanna’, ‘Director’),
   Employee(‘Henry’, ‘Admin’),
   Employee(‘Tim’, ‘Sales’),
   Employee(‘Juan’, ‘Admin’)
]

employees.sort(key' e -> e.name)

L(e) employees
   print(‘#<6 : #.’.format(e.name, e.category))
Output:
Alice  : Sales
David  : Manager
Henry  : Admin
Joanna : Director
Juan   : Admin
Tim    : Sales

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program shellSort64.s   */
 
/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"

/*******************************************/
/* Structures                               */
/********************************************/
/* city structure      */
    .struct  0
city_name:                             //
    .struct  city_name + 8             // string pointer
city_habitants:                        // 
    .struct  city_habitants + 8        // integer 
city_end:
 
/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessResult:        .asciz "Name : @  number habitants : @ \n"
szMessSortHab:      .asciz "Sort table for number of habitants :\n"
szMessSortName:     .asciz "Sort table for name of city :\n"
szCarriageReturn:   .asciz "\n"

// cities name
szCeret:           .asciz "Ceret"
szMaureillas:      .asciz "Maureillas"
szTaillet:         .asciz "Taillet"
szReynes:          .asciz "Reynes"
szVives:           .asciz "Vivés"
szBoulou:          .asciz "Le Boulou"
szSaintJean:       .asciz "Saint Jean Pla de Corts"
szCluses:          .asciz "Les Cluses"
szAlbere:          .asciz "L'Albère"
szPerthus:         .asciz "Le Perthus"

.align 4
TableCities:               
                 .quad szCluses         // address name string
                 .quad 251              // number of habitants
                 .quad szCeret
                 .quad 7705
                 .quad szMaureillas
                 .quad 2596
                 .quad szBoulou 
                 .quad 5554
                 .quad szSaintJean
                 .quad 2153
                 .quad szAlbere
                 .quad 83
                 .quad szVives
                 .quad 174
                 .quad szTaillet
                 .quad 115
                 .quad szPerthus
                 .quad 586
                 .quad szReynes
                 .quad 1354
.equ NBELEMENTS,  (. - TableCities) / city_end
                 .skip city_end         // temp area for element in shellSort
                                        // see other soluce to use stack 
                                        // in programm arm assembly in this forum
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:              .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                             // entry of program 
 
    ldr x0,qAdrszMessSortHab                      
    bl affichageMess

    ldr x0,qAdrTableCities        // address table
    mov x1,0                      // not use in routine
    mov x2,NBELEMENTS             // number of élements 
    mov x3,#city_habitants        // sort by number habitants
    mov x4,#'N'                   // numeric
    bl shellSort
    ldr x0,qAdrTableCities        // address table
    bl displayTable
 
     ldr x0,qAdrszMessSortName
    bl affichageMess

    ldr x0,qAdrTableCities        // address table
    mov x1,0                      // not use in routine
    mov x2,NBELEMENTS             // number of élements 
    mov x3,#city_name             // sort by city name
    mov x4,#'A'                   // alphanumeric
    bl shellSort
    ldr x0,qAdrTableCities        // address table
    bl displayTable
 
100:                              // standard end of the program 
    mov x0,0                      // return code
    mov x8,EXIT                   // request to exit program
    svc 0                         // perform the system call
 
qAdrsZoneConv:            .quad sZoneConv
qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrsMessResult:          .quad sMessResult
qAdrTableCities:          .quad TableCities
qAdrszMessSortHab:        .quad szMessSortHab
qAdrszMessSortName:        .quad szMessSortName
/***************************************************/
/*   shell Sort                                    */
/***************************************************/
/* x0 contains the address of table */
/* x1 contains the first element but not use !!   */
/*   this routine use first element at index zero !!!  */
/* x2 contains the number of element */
/* x3 contains the offset of sort zone */
/* x4 contains type of sort zone N = numeric A = alphanumeric */
shellSort:
    stp x1,lr,[sp,-16]!          // save  registers
    stp x2,x3,[sp,-16]!          // save  registers
    stp x4,x5,[sp,-16]!          // save  registers
    stp x6,x7,[sp,-16]!          // save  registers
    stp x8,x9,[sp,-16]!          // save  registers
    stp x10,x11,[sp,-16]!          // save  registers
    stp x12,x13,[sp,-16]!          // save  registers
    mov x8,x3                    // save offset area sort
    mov x9,x4                    // save type sort
    mov x7,city_end              // element size
    sub x12,x2,1                 // index last item
    mov x11,x12                  // init gap = last item
1:                               // start loop 1
    lsr x11,x11,1                // gap = gap / 2
    cbz x11,100f                 // if gap = 0 -> end
    mov x3,x11                   // init loop indice 1 
2:                               // start loop 2
    mul x1,x3,x7                 // offset élement
    mov x2,NBELEMENTS
    mul x2,x7,x2
    bl copyElement
    add x1,x1,x8                 // + offset sort zone
    ldr x4,[x0,x1]               // load first value
    mov x5,x3                    // init loop indice 2
3:                               // start loop 3
    cmp x5,x11                   // indice < gap
    blt 7f                       // yes -> end loop 2
    sub x6,x5,x11                // index = indice - gap
    mul x1,x6,x7                 // compute offset
    add x10,x1,x8                // + offset sort zone
    ldr x2,[x0,x10]              // load second value
    cmp x9,#'A'                  // sort area alapha ?
    beq 4f                       // yes
    cmp x4,x2                    //  else compare numeric values
    bge 7f                       // highter
    b 6f                         // lower
4:                               // compare area alphanumeric
    mov x10,#0                   // counter
5:
    ldrb w13,[x4,x10]            // byte string 1
    ldrb w6,[x2,x10]             // byte string 2
    cmp w13,w6
    bgt 7f                     
    blt 6f

    cmp w13,#0                   //  end string 1
    beq 7f                       // end comparaison
    add x10,x10,#1               // else add 1 in counter
    b 5b                         // and loop

6:
    mul x2,x5,x7                 // offset élement
    bl copyElement               // copy element x1 to element x2
    sub x5,x5,x11                // indice = indice - gap
    b 3b                         // and loop
7:
    mov x1,NBELEMENTS
    mul x1,x7,x1
    mul x2,x7,x5
    bl copyElement
    add x3,x3,1                  // increment indice 1
    cmp x3,x12                   // end ?
    ble 2b                       // no -> loop 2
    b 1b                         // yes loop for new gap
 
100:                             // end function
    ldp x12,x13,[sp],16          // restaur  2 registers
    ldp x10,x11,[sp],16          // restaur  2 registers
    ldp x8,x9,[sp],16            // restaur  2 registers
    ldp x6,x7,[sp],16            // restaur  2 registers
    ldp x4,x5,[sp],16            // restaur  2 registers
    ldp x2,x3,[sp],16            // restaur  2 registers
    ldp x1,lr,[sp],16            // restaur  2 registers
    ret                          // return to address lr x30

/******************************************************************/
/*      copy table element                                */ 
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 offset destination element */
copyElement:
    stp x1,lr,[sp,-16]!          // save  registers
    stp x2,x3,[sp,-16]!          // save  registers
    stp x4,x5,[sp,-16]!          // save  registers
    mov x3,0
    add x1,x1,x0
    add x2,x2,x0
1:
    ldrb w4,[x1,x3]
    strb w4,[x2,x3]
    add x3,x3,1
    cmp x3,city_end
    blt 1b
100:
    ldp x4,x5,[sp],16            // restaur  2 registers
    ldp x2,x3,[sp],16            // restaur  2 registers
    ldp x1,lr,[sp],16            // restaur  2 registers
    ret                          // return to address lr x30
/******************************************************************/
/*      Display table elements                                */ 
/******************************************************************/
/* x0 contains the address of table */
displayTable:
    stp x1,lr,[sp,-16]!          // save  registers
    stp x2,x3,[sp,-16]!          // save  registers
    stp x4,x5,[sp,-16]!          // save  registers
    stp x6,x7,[sp,-16]!          // save  registers
    mov x2,x0                    // table address
    mov x3,0
    mov x6,city_end
1:                               // loop display table
    mul x4,x3,x6
    add x4,x4,city_name
    ldr x1,[x2,x4]
    ldr x0,qAdrsMessResult
    bl strInsertAtCharInc        // put name in message
    mov x5,x0                     // save address of new message
    mul x4,x3,x6
    add x4,x4,city_habitants       // and load value
    ldr x0,[x2,x4]
    ldr x1,qAdrsZoneConv         // display value
    bl conversion10              // call function
    mov x0,x5
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc        // insert result at @ character
    bl affichageMess             // display message
    add x3,x3,1
    cmp x3,#NBELEMENTS - 1
    ble 1b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
100:
    ldp x6,x7,[sp],16            // restaur  2 registers
    ldp x4,x5,[sp],16            // restaur  2 registers
    ldp x2,x3,[sp],16            // restaur  2 registers
    ldp x1,lr,[sp],16            // restaur  2 registers
    ret                          // return to address lr x30
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
Sort table for number of habitants :
Name : L'Albère  number habitants : 83
Name : Taillet  number habitants : 115
Name : Vivés  number habitants : 174
Name : Les Cluses  number habitants : 251
Name : Le Perthus  number habitants : 586
Name : Reynes  number habitants : 1354
Name : Saint Jean Pla de Corts  number habitants : 2153
Name : Maureillas  number habitants : 2596
Name : Le Boulou  number habitants : 5554
Name : Ceret  number habitants : 7705

Sort table for name of city :
Name : Ceret  number habitants : 7705
Name : L'Albère  number habitants : 83
Name : Le Boulou  number habitants : 5554
Name : Le Perthus  number habitants : 586
Name : Les Cluses  number habitants : 251
Name : Maureillas  number habitants : 2596
Name : Reynes  number habitants : 1354
Name : Saint Jean Pla de Corts  number habitants : 2153
Name : Taillet  number habitants : 115
Name : Vivés  number habitants : 174

ACL2

(defun insert-by-key (o os key)
   (cond ((endp os) (list o))
         ((< (cdr (assoc key o))
             (cdr (assoc key (first os))))
          (cons o os))
         (t (cons (first os)
                  (insert-by-key o (rest os) key)))))

(defun isort-by-key (os key)
   (if (endp os)
       nil
       (insert-by-key (first os)
                      (isort-by-key (rest os) key)
                      key)))

(isort-by-key
 '(((name  . "map")
   (weight . 9)
   (value  . 150))
  ((name   . "compass")
   (weight . 13)
   (value  . 35))
  ((name   . "water")
   (weight . 153)
   (value  . 200))
  ((name   . "sandwich")
   (weight . 50)
   (value  . 60))
  ((name   . "glucose")
   (weight . 15)
   (value  . 60)))
 'value)

Output:

(((NAME . "compass")
  (WEIGHT . 13)
  (VALUE . 35))
 ((NAME . "glucose")
  (WEIGHT . 15)
  (VALUE . 60))
 ((NAME . "sandwich")
  (WEIGHT . 50)
  (VALUE . 60))
 ((NAME . "map")
  (WEIGHT . 9)
  (VALUE . 150))
 ((NAME . "water")
  (WEIGHT . 153)
  (VALUE . 200)))

Action!

DEFINE PTR="CARD"
DEFINE PAIR_SIZE="4"
DEFINE PAIR_COUNT="1"

TYPE Pair=[PTR name,value]

BYTE ARRAY pairs(100)
BYTE count=[0]

PTR FUNC GetItemAddr(INT index)
  PTR addr

  addr=pairs+index*PAIR_SIZE
RETURN (addr)

PROC PrintArray()
  INT i
  Pair POINTER p

  Put('[)
  FOR i=0 TO count-1
  DO
    IF i>0 THEN Put(' ) FI
    p=GetItemAddr(i)
    PrintF("(%S,%S)",p.name,p.value)
  OD
  Put(']) PutE()
RETURN

PROC Append(CHAR ARRAY n,v)
  Pair POINTER dst

  dst=GetItemAddr(count)
  dst.name=n
  dst.value=v
  count==+1
RETURN

PROC InitData()
  Append("Warsaw","Poland")
  Append("Prague","Czech Republic")
  Append("London","United Kingdom")
  Append("Paris","France")
  Append("Madrit","Spain")
  Append("Berlin","Germany")
  Append("Rome","Italy")
  Append("Moscow","Russia")
  Append("Budapest","Hungary")
RETURN

PROC Sort()
  INT i,j,minpos
  CHAR ARRAY tmp
  Pair POINTER p1,p2

  FOR i=0 TO count-2
  DO
    minpos=i
    FOR j=i+1 TO count-1
    DO
      p1=GetItemAddr(minpos)
      p2=GetItemAddr(j)
      IF SCompare(p1.name,p2.name)>0 THEN
        minpos=j
      FI
    OD
    
    IF minpos#i THEN
      p1=GetItemAddr(minpos)
      p2=GetItemAddr(i)
      tmp=p1.name p1.name=p2.name p2.name=tmp
      tmp=p1.value p1.value=p2.value p2.value=tmp
    FI
  OD
RETURN

PROC Main()
  InitData()
  PrintE("Array before sort:")
  PrintArray() PutE()
  
  Sort()
  PrintE("Array after sort:")
  PrintArray()
RETURN
Output:

Screenshot from Atari 8-bit computer

Array before sort:
[(Warsaw,Poland) (Prague,Czech Republic) (London,United Kingdom) (Paris,France) (Madrit,Spain) (Berlin,Germany) (Rome,Italy) (Moscow,Russia) (Budapest,Hungary)]

Array after sort:
[(Berlin,Germany) (Budapest,Hungary) (London,United Kingdom) (Madrit,Spain) (Moscow,Russia) (Paris,France) (Prague,Czech Republic) (Rome,Italy) (Warsaw,Poland)]

Ada

Ada 2005 defines 2 standard subprograms for sorting arrays - 1 for constrained arrays and 1 for unconstrained arrays. Below is a example of using the unconstrained version.

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;           use Ada.Text_IO;

with Ada.Containers.Generic_Array_Sort;

procedure Demo_Array_Sort is

   function "+" (S : String) return Unbounded_String renames To_Unbounded_String;

   type A_Composite is
      record
         Name  : Unbounded_String;
         Value : Unbounded_String;
      end record;

   function "<" (L, R : A_Composite) return Boolean is
   begin
      return L.Name < R.Name;
   end "<";

   procedure Put_Line (C : A_Composite) is
   begin
      Put_Line (To_String (C.Name) & " " & To_String (C.Value));
   end Put_Line;

   type An_Array is array (Natural range <>) of A_Composite;

   procedure Sort is new Ada.Containers.Generic_Array_Sort (Natural, A_Composite, An_Array);

   Data : An_Array := (1 => (Name => +"Joe",    Value => +"5531"),
                       2 => (Name => +"Adam",   Value => +"2341"),
                       3 => (Name => +"Bernie", Value => +"122"),
                       4 => (Name => +"Walter", Value => +"1234"),
                       5 => (Name => +"David",  Value => +"19"));

begin
   Sort (Data);
   for I in Data'Range loop
      Put_Line (Data (I));
   end loop;
end Demo_Array_Sort;

Result:

  C:\Ada\sort_composites\lib\demo_array_sort
  Adam 2341
  Bernie 122
  David 19
  Joe 5531
  Walter 1234

Ada 2005 also provides ordered containers, so no explicit call is required. Here is an example of an ordered set:

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;           use Ada.Text_IO;

with Ada.Containers.Ordered_Sets;

procedure Sort_Composites is

   function "+" (S : String) return Unbounded_String renames To_Unbounded_String;

   type A_Composite is
      record
         Name  : Unbounded_String;
         Value : Unbounded_String;
      end record;

   function "<" (L, R : A_Composite) return Boolean is
   begin
      return L.Name < R.Name;
   end "<";

   procedure Put_Line (C : A_Composite) is
   begin
      Put_Line (To_String (C.Name) & " " & To_String (C.Value));
   end Put_Line;

   package Composite_Sets is new Ada.Containers.Ordered_Sets (A_Composite);

   procedure Put_Line (C : Composite_Sets.Cursor) is
   begin
      Put_Line (Composite_Sets.Element (C));
   end Put_Line;

   Data : Composite_Sets.Set;

begin
   Data.Insert (New_Item => (Name => +"Joe",    Value => +"5531"));
   Data.Insert (New_Item => (Name => +"Adam",   Value => +"2341"));
   Data.Insert (New_Item => (Name => +"Bernie", Value => +"122"));
   Data.Insert (New_Item => (Name => +"Walter", Value => +"1234"));
   Data.Insert (New_Item => (Name => +"David",  Value => +"19"));
   Data.Iterate (Put_Line'Access);
end Sort_Composites;

Result:

  C:\Ada\sort_composites\lib\sort_composites
  Adam 2341
  Bernie 122
  David 19
  Joe 5531
  Walter 1234

There is no standard sort function for Ada 95. The example below implements a simple bubble sort.

with Ada.Text_Io;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Sort_Composite is
   type Composite_Record is record
      Name : Unbounded_String;
      Value : Unbounded_String;
   end record;
   
   type Pairs_Array is array(Positive range <>) of Composite_Record;
   
   procedure Swap(Left, Right : in out Composite_Record) is
      Temp : Composite_Record := Left;
   begin
      Left := Right;
      Right := Temp;
   end Swap; 
   
   -- Sort_Names uses a bubble sort
   
   procedure Sort_Name(Pairs : in out Pairs_Array) is
      Swap_Performed : Boolean := True;
   begin
      while Swap_Performed loop
         Swap_Performed := False;
         for I in Pairs'First..(Pairs'Last - 1) loop
            if Pairs(I).Name > Pairs(I + 1).Name then
               Swap (Pairs(I), Pairs(I + 1));
               Swap_Performed := True;
            end if;
         end loop;
      end loop;
   end Sort_Name;
   
   procedure Print(Item : Pairs_Array) is
   begin
      for I in Item'range loop
         Ada.Text_Io.Put_Line(To_String(Item(I).Name) & ", " & 
            to_String(Item(I).Value));
      end loop;
   end Print;
   type Names is (Fred, Barney, Wilma, Betty, Pebbles);
   type Values is (Home, Work, Cook, Eat, Bowl);
   My_Pairs : Pairs_Array(1..5);
begin
   for I in My_Pairs'range loop
      My_Pairs(I).Name := To_Unbounded_String(Names'Image(Names'Val(Integer(I - 1))));
      My_Pairs(I).Value := To_Unbounded_String(Values'Image(Values'Val(Integer(I - 1))));
   end loop;
   Print(My_Pairs);
   Ada.Text_Io.Put_Line("=========================");
   Sort_Name(My_Pairs);
   Print(My_Pairs);
end Sort_Composite;

ALGOL 68

Translation of: python
Works with: ALGOL 68 version Standard - with prelude inserted manually
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
MODE SORTSTRUCT = PERSON;
OP < = (PERSON a,b)BOOL: age OF a < age OF b;
PR READ "prelude/sort.a68" PR;

MODE PERSON = STRUCT (STRING name, INT age);
FORMAT person repr = $"Name: "g", Age: "g(0)l$;

[]SORTSTRUCT person = (("joe", 120), ("foo", 31), ("bar", 51));
printf((person repr, shell sort(person), $l$))

Output:

Name: foo, Age: 31
Name: bar, Age: 51
Name: joe, Age: 120

AppleScript

macOS Yosemite onwards, for import of Foundation framework

use framework "Foundation"

----- SORTING COMPOSITE STRUCTURES (BY MULTIPLE KEYS) ------

-- List of {strKey, blnAscending} pairs -> list of records -> sorted list of records

-- sortByComparing :: [(String, Bool)] -> [Record] -> [Record]
on sortByComparing(keyDirections, xs)
    set ca to current application
    
    script recDict
        on |λ|(x)
            ca's NSDictionary's dictionaryWithDictionary:x
        end |λ|
    end script
    set dcts to map(recDict, xs)
    
    script asDescriptor
        on |λ|(kd)
            set {k, d} to kd
            ca's NSSortDescriptor's sortDescriptorWithKey:k ascending:d selector:dcts
        end |λ|
    end script
    
    ((ca's NSArray's arrayWithArray:dcts)'s ¬
        sortedArrayUsingDescriptors:map(asDescriptor, keyDirections)) as list
end sortByComparing


--------------------------- TEST ---------------------------
on run
    set xs to [¬
        {city:"Shanghai ", pop:24.2}, ¬
        {city:"Karachi ", pop:23.5}, ¬
        {city:"Beijing ", pop:21.5}, ¬
        {city:"Sao Paulo ", pop:24.2}, ¬
        {city:"Dhaka ", pop:17.0}, ¬
        {city:"Delhi ", pop:16.8}, ¬
        {city:"Lagos ", pop:16.1}]
    
    -- Boolean true for ascending order, false for descending:
    
    sortByComparing([{"pop", false}, {"city", true}], xs)
end run


-------------------- GENERIC FUNCTIONS ---------------------

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map


-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn
Output:
{{pop:24.2, city:"Sao Paulo "}, {pop:24.2, city:"Shanghai "}, {pop:23.5, city:"Karachi "}, {pop:21.5, city:"Beijing "}, {pop:17.0, city:"Dhaka "}, {pop:16.8, city:"Delhi "}, {pop:16.1, city:"Lagos "}}

ARM Assembly

Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program compositeSort.s   */ 

/* REMARK 1 : this program use routines in a include file 
   see task Include a file language arm assembly 
   for the routine affichageMess conversion10 
   see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

/*******************************************/
/* Structures                               */
/********************************************/
/* city structure      */
    .struct  0
city_name:                             @ 
    .struct  city_name + 4 
city_habitants:                             @ 
    .struct  city_habitants + 4 
city_end:
/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessResult:        .asciz "Name : @  number habitants : @ \n"
szMessSortHab:      .asciz "Sort table for number of habitants :\n"
szMessSortName:     .asciz "Sort table for name of city :\n"
szCarriageReturn:   .asciz "\n"
 
// cities name
szCeret:           .asciz "Ceret"
szMaureillas:      .asciz "Maureillas"
szTaillet:         .asciz "Taillet"
szReynes:          .asciz "Reynes"
szVives:           .asciz "Vivés"
szBoulou:          .asciz "Le Boulou"
szSaintJean:       .asciz "Saint Jean Pla de Corts"
szCluses:          .asciz "Les Cluses"
szAlbere:          .asciz "L'Albère"
szPerthus:         .asciz "Le Perthus"
.align 4

TableCities:               
                 .int szCluses         @ address name string
                 .int 251              @ number of habitants
                 .int szCeret
                 .int 7705
                 .int szMaureillas
                 .int 2596
                 .int szBoulou 
                 .int 5554
                 .int szSaintJean
                 .int 2153
                 .int szAlbere
                 .int 83
                 .int szVives
                 .int 174
                 .int szTaillet
                 .int 115
                 .int szPerthus
                 .int 586
                 .int szReynes
                 .int 1354
.equ NBELEMENTS,  (. - TableCities) / city_end
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:        .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                             @ entry of program 
 
    ldr r0,iAdrszMessSortHab                      
    bl affichageMess

    ldr r0,iAdrTableCities                        @ address city table
    mov r1,#0                                     @ not use in routine
    mov r2,#NBELEMENTS                            @ number of élements 
    mov r3,#city_habitants                        @ sort by number habitants
    mov r4,#'N'                                   @ Alphanumeric
    bl shellSort
    ldr r0,iAdrTableCities                        @ address number table
    bl displayTable
    
    ldr r0,iAdrszMessSortName                      
    bl affichageMess
 
    ldr r0,iAdrTableCities                        @ address city table
    mov r1,#0                                     @ not use in routine
    mov r2,#NBELEMENTS                            @ number of élements 
    mov r3,#city_name                             @ sort by name
    mov r4,#'A'                                   @ Alphanumeric
    bl shellSort
    ldr r0,iAdrTableCities                        @ address number table
    bl displayTable

100:                                              @ standard end of the program 
    mov r0, #0                                    @ return code
    mov r7, #EXIT                                 @ request to exit program
    svc #0                                        @ perform the system call
 
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrsMessResult:          .int sMessResult
iAdrTableCities:          .int TableCities
iAdrszMessSortHab:        .int szMessSortHab
iAdrszMessSortName:       .int szMessSortName
/***************************************************/
/*   shell Sort                                    */
/***************************************************/

/* r0 contains the address of table */
/* r1 contains the first element but not use !!   */
/*   this routine use first element at index zero !!!  */
/* r2 contains the number of element */
/* r3 contains the offset of sort zone */
/* r4 contains type of sort zone N = numeric A = alphanumeric */
shellSort:
    push {r0-r12,lr}             @ save registers
    sub sp,#city_end             @ reserve area on stack
    mov fp,sp                    @ frame pointer = stack
    mov r8,r3                    @ save offser area sort
    mov r9,r4                    @ save type sort
    mov r7,#city_end             @ element size
    //vidregtit debut
    sub r12,r2,#1                @ index last item
    mov r6,r12                   @ init gap = last item
1:                               @ start loop 1
    lsrs r6,#1                   @ gap = gap / 2
    beq 100f                     @ if gap = 0 -> end
    mov r3,r6                    @ init loop indice 1 
2:                               @ start loop 2
    mul r1,r3,r7                 @ offset élement
    mov r2,fp                    @ save on stack
    bl saveElement 
    add r1,r8                    @ + offset sort zone
    ldr r4,[r0,r1]               @ load first value
    mov r5,r3                    @ init loop indice 2
3:                               @ start loop 3
    cmp r5,r6                    @ indice < gap
    blt 8f                       @ yes -> end loop 2
    sub r10,r5,r6                @ index = indice - gap
    mul r1,r10,r7                @ offset élement
    add r10,r1,r8                @ + offset sort zone
    ldr r2,[r0,r10]              @ load second value
    push {r3,r5}                 @ save registrars because not enought register
    cmp r9,#'A'                  @ sort area alapha ?
    beq 4f                       @ yes
    cmp r4,r2                    @  else compare numeric values
    bge 7f                       @ highter
    b 6f                         @ lower
4:                               @ compare area alphanumeric
    mov r10,#0                   @ counter
5:
    ldrb r3,[r4,r10]             @ byte string 1
    ldrb r5,[r2,r10]             @ byte string 2
    cmp r3,r5
    bgt 7f                     
    blt 6f

    cmp r3,#0                    @  end string 1
    beq 7f                       @ ens comparaison
    add r10,r10,#1               @ else add 1 in counter
    b 5b                         @ and loop
     
6:
    pop {r3,r5}                  @ restaur registers
    mul r2,r5,r7                 @ offset élement
    bl copyElement               @ copy element r1 to element r2
    sub r5,r6                    @ indice = indice - gap
    b 3b                         @ and loop
7:
    pop {r3,r5}
8:                               @ end loop 3
    mul r1,r5,r7                 @ offset destination élement 
    mov r2,fp                    @ restaur element in table
    bl restaurElement 
    add r3,#1                    @ increment indice 1
    cmp r3,r12                   @ end ?
    ble 2b                       @ no -> loop 2
    b 1b                         @ yes loop for new gap
 
100:                             @ end function
    add sp,#city_end 
    pop {r0-r12,lr}              @ restaur registers
    bx lr                        @ return 
/******************************************************************/
/*      copy table element                                */ 
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 offset destination element */
copyElement:
    push {r0-r4,lr}                                    @ save registers
    //vidregtit copy
    mov r3,#0
    add r1,r0
    add r2,r0
1:
    ldrb r4,[r1,r3]
    strb r4,[r2,r3]
    add r3,#1
    cmp r3,#city_end
    blt 1b
100:
    pop {r0-r4,lr}
    bx lr
/******************************************************************/
/*      save element                                */ 
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 address destination  */
saveElement:
    push {r0-r4,lr}                                    @ save registers
    mov r3,#0
    add r1,r0
1:
    ldrb r4,[r1,r3]
    strb r4,[r2,r3]
    add r3,#1
    cmp r3,#city_end
    blt 1b
100:
    pop {r0-r4,lr}
    bx lr
/******************************************************************/
/*      restaur element                                */ 
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset destination element */
/* r2 address origine  */
restaurElement:
    push {r0-r4,lr}                                    @ save registers
    mov r3,#0
    add r1,r0
1:
    ldrb r4,[r2,r3]
    strb r4,[r1,r3]
    add r3,#1
    cmp r3,#city_end
    blt 1b
100:
    pop {r0-r4,lr}
    bx lr
/******************************************************************/
/*      Display table elements                                */ 
/******************************************************************/
/* r0 contains the address of table */
displayTable:
    push {r0-r6,lr}              @ save registers
    mov r2,r0                    @ table address
    mov r3,#0
    mov r6,#city_end
1:                               @ loop display table
    mul r4,r3,r6
    add r4,#city_name
    ldr r1,[r2,r4]
    ldr r0,iAdrsMessResult
    bl strInsertAtCharInc        @ put name in message
    mov r5,r0                    @ save address of new message
    mul r4,r3,r6
    add r4,#city_habitants       @ and load value
    ldr r0,[r2,r4]
    ldr r1,iAdrsZoneConv
    bl conversion10              @ call decimal conversion
    mov r0,r5
    ldr r1,iAdrsZoneConv         @ insert conversion in message
    bl strInsertAtCharInc
    bl affichageMess             @ display message
    add r3,#1
    cmp r3,#NBELEMENTS - 1
    ble 1b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
100:
    pop {r0-r6,lr}
    bx lr
iAdrsZoneConv:      .int sZoneConv

/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
Sort table for number of habitants :
Name : L'Albère  number habitants : 83
Name : Taillet  number habitants : 115
Name : Vivés  number habitants : 174
Name : Les Cluses  number habitants : 251
Name : Le Perthus  number habitants : 586
Name : Reynes  number habitants : 1354
Name : Saint Jean Pla de Corts  number habitants : 2153
Name : Maureillas  number habitants : 2596
Name : Le Boulou  number habitants : 5554
Name : Ceret  number habitants : 7705

Sort table for name of city :
Name : Ceret  number habitants : 7705
Name : L'Albère  number habitants : 83
Name : Le Boulou  number habitants : 5554
Name : Le Perthus  number habitants : 586
Name : Les Cluses  number habitants : 251
Name : Maureillas  number habitants : 2596
Name : Reynes  number habitants : 1354
Name : Saint Jean Pla de Corts  number habitants : 2153
Name : Taillet  number habitants : 115
Name : Vivés  number habitants : 174

Arturo

people: [
    ["joe" 120]
    ["foo" 31]
    ["bar" 51]
]

print arrange people 'x -> x\0
Output:
[bar 51] [foo 31] [joe 120]

ATS

#include "share/atspre_staload.hats"

typedef pair =
  '{
    name = string,
    value = string
  }

fn
sort_pairs {n     : int}
           (pairs : &array (pair, n) >> _,
            n     : size_t n)
    :<!wrt> void =
  let
    implement
    array_quicksort$cmp<pair> (x, y) =
      strcmp (x.name, y.name)
  in
    array_quicksort<pair> (pairs, n)
  end

implement
main0 () =
  let
    val pairs_list : list (pair, 9) =
      $list
        ('{name = "Warsaw",   value = "Poland"},
         '{name = "Prague",   value = "Czech Republic"},
         '{name = "London",   value = "United Kingdom"},
         '{name = "Paris",    value = "France"},
         '{name = "Madrid",   value = "Spain"},
         '{name = "Berlin",   value = "Germany"},
         '{name = "Rome",     value = "Italy"},
         '{name = "Moscow",   value = "Russia"},
         '{name = "Budapest", value = "Hungary"})

    var pairs_array : @[pair][9]
    val () = array_initize_list<pair> (pairs_array, 9, pairs_list)

    val () = sort_pairs (pairs_array, i2sz 9)

    var i : [i : nat | i <= 9] int i
  in
    for (i := 0; i <> 9; i := succ i)
      println! (pairs_array[i].name, " -> ", pairs_array[i].value)
  end
Output:
$ patscc -DATS_MEMALLOC_GCBDW -O3 sort_composite_structures.dats -lgc && ./a.out
Berlin -> Germany
Budapest -> Hungary
London -> United Kingdom
Madrid -> Spain
Moscow -> Russia
Paris -> France
Prague -> Czech Republic
Rome -> Italy
Warsaw -> Poland

AutoHotkey

built ListView Gui, contains a table sorting function which can be used for this.

start:
Gui, Add, ListView, r20 w200, 1|2
data =
(
foo,53
joe,34
bar,23
)

Loop, parse, data, `n
{
  stringsplit, row, A_LoopField, `,
  LV_Add(row, row1, row2)
}
LV_ModifyCol()  ; Auto-size columns
Gui, Show
msgbox, sorting by column1
LV_ModifyCol(1, "sort") ; sort by first column
msgbox, sorting by column2
LV_ModifyCol(2, "sort Integer") ; sort by second column numerically
return

GuiClose:
ExitApp

AWK

# syntax: GAWK -f SORT_AN_ARRAY_OF_COMPOSITE_STRUCTURES.AWK
BEGIN {
# AWK lacks structures but one can be simulated using an associative array.
    arr["eight  8 "]
    arr["two    2 "]
    arr["five   5 "]
    arr["nine   9 "]
    arr["one    1 "]
    arr["three  3 "]
    arr["six    6 "]
    arr["seven  7 "]
    arr["four   4 "]
    arr["ten    10"]
    arr["zero   0 "]
    arr["twelve 12"]
    arr["minus2 -2"]
    show(1,7,"@val_str_asc","name") # use name part of name-value pair
    show(8,9,"@val_num_asc","value") # use value part of name-value pair
    exit(0)
}
function show(a,b,sequence,description,  i,x) {
    PROCINFO["sorted_in"] = "@unsorted"
    for (i in arr) {
      x = substr(i,a,b)
      sub(/ +/,"",x)
      arr[i] = x
    }
    PROCINFO["sorted_in"] = sequence
    printf("sorted by %s:",description)
    for (i in arr) {
      printf(" %s",arr[i])
    }
    printf("\n")
}
Output:
sorted by name: eight five four minus2 nine one seven six ten three twelve two zero
sorted by value: -2 0 1 2 3 4 5 6 7 8 9 10 12

Babel

First, we construct a list-of-maps and assign it to variable baz. Next, we sort baz by key "foo" and assign it to variable bop. Finally, we lookup "foo" in each map in list bop and display the resulting list of numbers - they are in sorted order.

babel> baz ([map "foo" 3 "bar" 17] [map "foo" 4 "bar" 18] [map "foo" 5 "bar" 19] [map "foo" 0 "bar" 20]) <
babel> bop baz { <- "foo" lumap ! -> "foo" lumap ! lt? } lssort ! <
babel> bop {"foo" lumap !} over ! lsnum !
( 0 3 4 5 )

The same technique works for any list of data-objects you may have. User-code can expect to have the top two elements of the stack set to be the two objects to be compared. Simply access the relevant field in each object, and then perform a comparison. For example, here is a list of pairs sorted by first element:

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
( 11 10 )
( 15 13 )
( 12 16 )
( 17 3 )
( 14 5 )
( 4 19 )
( 18 9 )
( 1 7 )
( 8 6 )
( 0 2 )
babel> {<- car -> car lt? } lssort ! --> sort the list by first element of each pair
babel> dup {lsnum !} ... --> display the sorted list, pair-by-pair
( 0 2 )
( 1 7 )
( 4 19 )
( 8 6 )
( 11 10 )
( 12 16 )
( 14 5 )
( 15 13 )
( 17 3 )
( 18 9 )

The gpsort utility performs this kind of comparison "automagically" by leveraging the ordering of Babel's underlying data-structure. Using the shuffled list from the example above:

babel> gpsort !
babel> dup {lsnum !} ...
( 0 2 )
( 1 7 )
( 4 19 )
( 8 6 )
( 11 10 )
( 12 16 )
( 14 5 )
( 15 13 )
( 17 3 )
( 18 9 )

Note that gpsort will not work for the case where you want to sort on the second element of a list of pairs. But it will work for performing a canonical sort on numbers, arrays of numbers, lists of numbers, lists of lists, lists of arrays, arrays of lists, and so on. You should not use gpsort with strings; use lexsort or strsort instead. Here's an example of sorting a mixture of pairs and triples using gpsort:

babel> dup {lsnum !} ... --> display the shuffled list of pairs and triples
( 7 2 )
( 6 4 )
( 8 9 )
( 0 5 )
( 5 14 0 )
( 3 1 )
( 9 6 10 )
( 1 12 4 )
( 11 13 7 )
( 8 2 3 )
babel> gpsort ! --> sort the list
babel> dup {lsnum !} ... --> display the result
( 0 5 )
( 3 1 )
( 6 4 )
( 7 2 )
( 8 9 )
( 1 12 4 )
( 5 14 0 )
( 8 2 3 )
( 9 6 10 )
( 11 13 7 )

BBC BASIC

Uses the supplied SORTSALIB library.

      INSTALL @lib$+"SORTSALIB"
      sort% = FN_sortSAinit(0,0)
      
      DIM pair{name$, number%}
      DIM array{(10)} = pair{}
      FOR i% = 1 TO DIM(array{()}, 1)
        READ array{(i%)}.name$, array{(i%)}.number%
      NEXT
      
      DATA "Eight", 8, "Two", 2, "Five", 5, "Nine", 9, "One", 1
      DATA "Three", 3, "Six", 6, "Seven", 7, "Four", 4, "Ten", 10
      
      C% = DIM(array{()}, 1)
      D% = 1
      CALL sort%, array{()}, array{(0)}.number%, array{(0)}.name$
      
      FOR i% = 1 TO DIM(array{()}, 1)
        PRINT array{(i%)}.name$, array{(i%)}.number%
      NEXT

Output:

One                1
Two                2
Three              3
Four               4
Five               5
Six                6
Seven              7
Eight              8
Nine               9
Ten               10

Bracmat

The easiest way to sort an array of elements in Bracmat is to handle it as a sum of terms. A sum, when evaluated, is automatically sorted.

( (tab=("C++",1979)+(Ada,1983)+(Ruby,1995)+(Eiffel,1985))
& out$"unsorted array:"
& lst$tab
& out$("sorted array:" !tab \n)
& out$"But tab is still unsorted:"
& lst$tab
);

Output:

unsorted array:
(tab=
("C++",1979)+(Ada,1983)+(Ruby,1995)+(Eiffel,1985)
);
  sorted array:
  (Ada,1983)+(C++,1979)+(Eiffel,1985)+(Ruby,1995)


But tab is still unsorted:
(tab=
("C++",1979)+(Ada,1983)+(Ruby,1995)+(Eiffel,1985)
);

When evaluating !tab, the expression bound to the variable name tab is sorted, but the unevaluated expression is still bound to tab. An assignment binds the sorted expression to tab:

( !tab:?tab
& out$"Now tab is sorted:"
& lst$tab
);

Output:

Now tab is sorted:
(tab=
(Ada,1983)+("C++",1979)+(Eiffel,1985)+(Ruby,1995)
);

To sort an array that is not a sum expression, we can convert it to a sum:

(     ((name.map),(weight.9),(value.150))
      ((name.compass),(weight.13),(value.35))
      ((name.water),(weight.153),(value.200))
      ((name.sandwich),(weight.50),(value.60))
      ((name.glucose),(weight.15),(value.60))
  : ?array
& ( reverse
  =   e A
    .   :?A
      & whl'(!arg:%?e ?arg&!e !A:?A)
      & !A
  )
& out$("Array before sorting:" !array \n)
& 0:?sum
&   whl
  ' (!array:%?element ?array&!element+!sum:?sum)
&   whl
  ' (!sum:%?element+?sum&!element !array:?array)
& out$("Array after sorting (descending order):" !array \n)
& out$("Array after sorting (ascending order):" reverse$!array \n)
);

Output:

  Array before sorting:
  ((name.map),(weight.9),(value.150))
  ((name.compass),(weight.13),(value.35))
  ((name.water),(weight.153),(value.200))
  ((name.sandwich),(weight.50),(value.60))
  ((name.glucose),(weight.15),(value.60))


  Array after sorting (descending order):
  ((name.water),(weight.153),(value.200))
  ((name.sandwich),(weight.50),(value.60))
  ((name.map),(weight.9),(value.150))
  ((name.glucose),(weight.15),(value.60))
  ((name.compass),(weight.13),(value.35))


  Array after sorting (ascending order):
  ((name.compass),(weight.13),(value.35))
  ((name.glucose),(weight.15),(value.60))
  ((name.map),(weight.9),(value.150))
  ((name.sandwich),(weight.50),(value.60))
  ((name.water),(weight.153),(value.200))

Bracmat has a left to right sorting order. If an array must be sorted on another field than the first field, that other field has to be made the first field. After sorting, the fields can take their original positions.

(     (Joe,5531)
      (Adam,2341)
      (Bernie,122)
      (Walter,1234)
      (David,19)
  : ?array
& 0:?sum
&   whl
  ' ( !array:(?car,?cdr) ?array
    & (!cdr.!car)+!sum:?sum
    )
&   whl
  ' ( !sum:(?car.?cdr)+?sum
    & (!cdr,!car) !array:?array
    )
& out$("Array after sorting on second field (descending order):" !array \n)
&   out
  $ ( "Array after sorting on second field (ascending order):"
      reverse$!array
      \n
    )
);

Output:

  Array after sorting on second field (descending order):
  (Joe,5531)
  (Adam,2341)
  (Walter,1234)
  (Bernie,122)
  (David,19)


  Array after sorting on second field (ascending order):
  (David,19)
  (Bernie,122)
  (Walter,1234)
  (Adam,2341)
  (Joe,5531)

C

Using qsort, from the standard library.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct twoStringsStruct {
    char * key, *value;
} sTwoStrings;
 
int ord( char v )
{
    static char *dgts = "012345679";
    char *cp;
    for (cp=dgts; v != *cp; cp++);
    return (cp-dgts);
}

int cmprStrgs(const sTwoStrings *s1,const sTwoStrings *s2)
{
    char *p1 = s1->key; 
    char *p2 = s2->key;
    char *mrk1, *mrk2;
    while ((tolower(*p1) == tolower(*p2)) && *p1) { p1++; p2++;}
    if (isdigit(*p1) && isdigit(*p2)) {
        long v1, v2;
        if ((*p1 == '0') ||(*p2 == '0')) {
            while (p1 > s1->key) {
                p1--; p2--;
                if (*p1 != '0') break;
            }
            if (!isdigit(*p1)) {
                p1++; p2++;
            }
        }
        mrk1 = p1; mrk2 = p2;
        v1 = 0;
        while(isdigit(*p1)) {
            v1 = 10*v1+ord(*p1);
            p1++;
        }
        v2 = 0;
        while(isdigit(*p2)) {
            v2 = 10*v2+ord(*p2);
            p2++;
        }
        if (v1 == v2) 
           return(p2-mrk2)-(p1-mrk1);
        return v1 - v2;
    }
    if (tolower(*p1) != tolower(*p2))
       return (tolower(*p1) - tolower(*p2));
    for(p1=s1->key, p2=s2->key; (*p1 == *p2) && *p1; p1++, p2++);
    return (*p1 -*p2);
}

int maxstrlen( char *a, char *b)
{
	int la = strlen(a);
	int lb = strlen(b);
	return (la>lb)? la : lb;
}

int main()
{
    sTwoStrings toBsorted[] = {
        { "Beta11a", "many" },
        { "alpha1", "This" },
        { "Betamax", "sorted." },
        { "beta3", "order" },
        { "beta11a", "strings" },
        { "beta001", "is" },
        { "beta11", "which" },
        { "beta041", "be" },
        { "beta05", "in" },
        { "beta1", "the" },
        { "beta40", "should" },
    };
#define ASIZE (sizeof(toBsorted)/sizeof(sTwoStrings))
    int k, maxlens[ASIZE];
    char format[12];
    sTwoStrings *cp;

    qsort( (void*)toBsorted, ASIZE, sizeof(sTwoStrings),cmprStrgs); 

    for (k=0,cp=toBsorted; k < ASIZE; k++,cp++) {
        maxlens[k] = maxstrlen(cp->key, cp->value);   
        sprintf(format," %%-%ds", maxlens[k]);
        printf(format, toBsorted[k].value);
	}
    printf("\n");
    for (k=0; k < ASIZE; k++) {
        sprintf(format," %%-%ds", maxlens[k]);
        printf(format, toBsorted[k].key);
	}
    printf("\n");

  return 0;
}

Output:

   This      is   the order     in  which    many strings should      be sorted.
 alpha1 beta001 beta1 beta3 beta05 beta11 Beta11a beta11a beta40 beta041 Betamax

C#

Works with: C# version 3+
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{        
    struct Entry
    {
        public Entry(string name, double value) { Name = name; Value = value; }
        public string Name;
        public double Value;
    }

    static void Main(string[] args)
    {
        var Elements = new List<Entry>
        {
            new Entry("Krypton", 83.798), new Entry("Beryllium", 9.012182), new Entry("Silicon", 28.0855),
            new Entry("Cobalt", 58.933195), new Entry("Selenium", 78.96), new Entry("Germanium", 72.64)
        };

        var sortedElements = Elements.OrderBy(e => e.Name);

        foreach (Entry e in sortedElements)
            Console.WriteLine("{0,-11}{1}", e.Name, e.Value);
    }
}

Output:

Beryllium  9.012182
Cobalt     58.933195
Germanium  72.64
Krypton    83.798
Selenium   78.96
Silicon    28.0855

C++

Uses C++11. Compile with

g++ -std=c++11 sort.cpp
#include <algorithm>
#include <iostream>
#include <string>

struct entry {
  std::string name;
  std::string value;
};

int main() {
  entry array[] = { { "grass", "green" }, { "snow", "white" },
                    { "sky", "blue" }, { "cherry", "red" } };

  std::cout << "Before sorting:\n";
  for (const auto &e : array) {
    std::cout << "{" << e.name << ", " << e.value << "}\n";
  }

  std::sort(std::begin(array), std::end(array), 
            [](const entry & a, const entry & b) {
    return a.name < b.name;
  });

  std::cout << "After sorting:\n";
  for (const auto &e : array) {
    std::cout << "{" << e.name << ", " << e.value << "}\n";
  }
}

Output:

Before sorting:
{grass, green}
{snow, white}
{sky, blue}
{cherry, red}
After sorting:
{cherry, red}
{grass, green}
{sky, blue}
{snow, white}

Clojure

Clojure has a sort-by function which takes a keyfn and a coll. It returns a sorted sequence of the items in coll, where the sort order is determined by comparing (keyfn item).

;; Gathered with Google Squared
(def *langs* [["Clojure" 2007] ["Common Lisp" 1984] ["Java" 1995] ["Haskell" 1990]
              ["Lisp" 1958] ["Scheme" 1975]])

user> (sort-by second *langs*) ; using a keyfn

(["Lisp" 1958] ["Scheme" 1975] ["Common Lisp" 1984] ["Haskell" 1990] ["Java" 1995] ["Clojure" 2007])

You can also supply a comparator (using compare or a sibling of <). A comparator can be used with the regular sort function or the sort-by function. In the latter case, the comparator will be used on (keyfn item) instead of item.

user> (sort #(compare (second %1) (second %2)) *langs*) ; using a comparator

(["Lisp" 1958] ["Scheme" 1975] ["Common Lisp" 1984] ["Haskell" 1990] ["Java" 1995] ["Clojure" 2007])

user> (sort-by second > *langs*) ; using a keyfn and a comparator

(["Clojure" 2007] ["Java" 1995] ["Haskell" 1990] ["Common Lisp" 1984] ["Scheme" 1975] ["Lisp" 1958])

Read the docstring of sort and sort-by for more info.

Common Lisp

In Common Lisp, the sort function takes a predicate that is used as the comparator. This parameter can be any two-argument function. Additionally, the sort function can take a keyword argument :key whose result is passed to the predicate.

Let's define a composite structure of U.S. states and average test scores.

CL-USER> (defparameter *test-scores* '(("texas" 68.9) ("ohio" 87.8) ("california" 76.2) ("new york" 88.2)) )
*TEST-SCORES*

We can sort by the state name by supplying a one-argument key function that is called by the sort function to determine the value to compare. In this case, the function is first will retrieve the state name:

CL-USER> (sort (copy-list *test-scores*) #'string-lessp :key #'first)
(("california" 76.2) ("new york" 88.2) ("ohio" 87.8) ("texas" 68.9))

we can also sort by the test scores by supplying a different key function that return the test score instead:

CL-USER> (sort (copy-list *test-scores*) #'< :key #'second)
(("texas" 68.9) ("california" 76.2) ("ohio" 87.8) ("new york" 88.2))

D

import std.stdio, std.algorithm;

struct Pair { string name, value; }

void main() {
    Pair[] pairs = [{"Joe",    "5531"},
                    {"Adam",   "2341"},
                    {"Bernie",  "122"},
                    {"Walter", "1234"},
                    {"David",    "19"}];

    pairs.schwartzSort!q{ a.name }.writeln;
}
Output:
[Pair("Adam", "2341"), Pair("Bernie", "122"), Pair("David", "19"), Pair("Joe", "5531"), Pair("Walter", "1234")]

Delphi

program SortCompositeStructures;

{$APPTYPE CONSOLE}

uses SysUtils, Generics.Collections, Generics.Defaults;

type
  TStructurePair = record
    name: string;
    value: string;
    constructor Create(const aName, aValue: string);
  end;

constructor TStructurePair.Create(const aName, aValue: string);
begin
  name := aName;
  value := aValue;
end;

var
  lArray: array of TStructurePair;
begin
  SetLength(lArray, 3);
  lArray[0] := TStructurePair.Create('dog', 'rex');
  lArray[1] := TStructurePair.Create('cat', 'simba');
  lArray[2] := TStructurePair.Create('horse', 'trigger');

  TArray.Sort<TStructurePair>(lArray , TDelegatedComparer<TStructurePair>.Construct(
  function(const Left, Right: TStructurePair): Integer
  begin
    Result := CompareText(Left.Name, Right.Name);
  end));
end.

E

def compareBy(keyfn) { # This ought to be in the standard library
  return def comparer(a, b) {
    return keyfn(a).op__cmp(keyfn(b))
  }
}

def x := [
  ["Joe",3],
  ["Bill",4],
  ["Alice",20],
  ["Harry",3],
]

println(x.sort(compareBy(fn [name,_] { name })))

EchoLisp

;; sorting (name value) by name - Ignoring case
(define (name a) (first a))
(define( sort-proc a b)
    (string-ci<? (name a) (name b)))

(define people 
   '(("😎" -42) ("albert" 33) ("Simone" 44) ("Antoinette" 42) ("elvis" 666) ("😃" 1000)))

(list-sort sort-proc people)
    (("albert" 33) ("Antoinette" 42) ("elvis" 666) ("Simone" 44) ("😃" 1000) ("😎" -42))

Elena

ELENA 6.x :

import system'routines;
import extensions;
 
public program()
{
    var elements := new object[]{
            KeyValue.new("Krypton", 83.798r),
            KeyValue.new("Beryllium", 9.012182r),
            KeyValue.new("Silicon", 28.0855r),
            KeyValue.new("Cobalt", 58.933195r),
            KeyValue.new("Selenium", 78.96r),
            KeyValue.new("Germanium", 72.64r)};
 
    var sorted := elements.sort::(former,later => former.Key < later.Key );
 
    sorted.forEach::(element)
    {
         console.printLine(element.Key," - ",element)
    }
}

Elixir

defmodule Person do
  defstruct name: "", value: 0
end

list = [struct(Person, [name: "Joe", value: 3]),
        struct(Person, [name: "Bill", value: 4]),
        struct(Person, [name: "Alice", value: 20]),
        struct(Person, [name: "Harry", value: 3])]

Enum.sort(list) |> Enum.each(fn x -> IO.inspect x end)
IO.puts ""
Enum.sort_by(list, &(&1.value)) |> Enum.each(&IO.inspect &1)
Output:
%Person{name: "Alice", value: 20}
%Person{name: "Bill", value: 4}
%Person{name: "Harry", value: 3}
%Person{name: "Joe", value: 3}

%Person{name: "Joe", value: 3}
%Person{name: "Harry", value: 3}
%Person{name: "Bill", value: 4}
%Person{name: "Alice", value: 20}

Erlang

Any Erlang type can be compared to any Erlang type. As such, nothing special needs to be done:

1> lists:sort([{{2006,2007},"Ducks"},
               {{2000,2001},"Avalanche"},
               {{2002,2003},"Devils"},
               {{2001,2002},"Red Wings"},
               {{2003,2004},"Lightning"},
               {{2004,2005},"N/A: lockout"},
               {{2005,2006},"Hurricanes"},
               {{1999,2000},"Devils"},
               {{2007,2008},"Red Wings"},
               {{2008,2009},"Penguins"}]).
[{{1999,2000},"Devils"},
 {{2000,2001},"Avalanche"},
 {{2001,2002},"Red Wings"},
 {{2002,2003},"Devils"},
 {{2003,2004},"Lightning"},
 {{2004,2005},"N/A: lockout"},
 {{2005,2006},"Hurricanes"},
 {{2006,2007},"Ducks"},
 {{2007,2008},"Red Wings"},
 {{2008,2009},"Penguins"}]

It is also possible to sort with custom functions, in this case by the team's name:

2> F = fun({_,X},{_,Y}) -> X < Y end.   
#Fun<erl_eval.12.113037538>
3> lists:usort(F, [{{2006,2007},"Ducks"},
                   {{2000,2001},"Avalanche"},
                   {{2002,2003},"Devils"},
                   {{2001,2002},"Red Wings"},
                   {{2003,2004},"Lightning"},
                   {{2004,2005},"N/A: lockout"},
                   {{2005,2006},"Hurricanes"},
                   {{1999,2000},"Devils"},
                   {{2007,2008},"Red Wings"},
                   {{2008,2009},"Penguins"}]).
[{{2000,2001},"Avalanche"},
 {{1999,2000},"Devils"},
 {{2002,2003},"Devils"},
 {{2006,2007},"Ducks"},
 {{2005,2006},"Hurricanes"},
 {{2003,2004},"Lightning"},
 {{2004,2005},"N/A: lockout"},
 {{2008,2009},"Penguins"},
 {{2007,2008},"Red Wings"},
 {{2001,2002},"Red Wings"}]

Euphoria

include sort.e
include misc.e

constant NAME = 1
function compare_names(sequence a, sequence b)
    return compare(a[NAME],b[NAME])
end function

sequence s
s = { { "grass",  "green" },
      { "snow",   "white" },
      { "sky",    "blue"  },
      { "cherry", "red"   } }

pretty_print(1,custom_sort(routine_id("compare_names"),s),{2})

Output:

{
  {
    "cherry",
    "red"
  },
  {
    "grass",
    "green"
  },
  {
    "sky",
    "blue"
  },
  {
    "snow",
    "white"
  }
}

F#

F# has sortBy functions that work on collection types for this purpose. An example using an array of pairs:

let persons = [| ("Joe", 120); ("foo", 31); ("bar", 51) |]
Array.sortInPlaceBy fst persons
printfn "%A" persons

Output:

[|("Joe", 120); ("bar", 51); ("foo", 31)|]

An example using a list of records:

type Person = { name:string; id:int }
let persons2 = [{name="Joe"; id=120}; {name="foo"; id=31}; {name="bar"; id=51}]
let sorted = List.sortBy (fun p -> p.id) persons2
for p in sorted do printfn "%A" p

Output:

{name = "foo";
 id = 31;}
{name = "bar";
 id = 51;}
{name = "Joe";
 id = 120;}

Factor

This is essentially the same as Sorting Using a Custom Comparator.

TUPLE: example-pair name value ;

: sort-by-name ( seq -- seq' ) [ [ name>> ] compare ] sort ;
( scratchpad ) { T{ example-pair f "omega" "a" } T{ example-pair f "gamma" "q" } T{ example-pair f "alpha" "z" } } sort-by-name .
{
    T{ example-pair { name "alpha" } { value "z" } }
    T{ example-pair { name "gamma" } { value "q" } }
    T{ example-pair { name "omega" } { value "a" } }
}

Fantom

Any object can be sorted as needed by passing an appropriate block to the 'sort' method.

class Pair // create a composite structure
{
  Str name
  Str value
  new make (Str name, Str value)
  {
    this.name = name
    this.value = value
  }

  override Str toStr () 
  {
    "(Pair: $name, $value)"
  }
}

class Main
{
  public static Void main ()
  {
    // samples
    pairs := [Pair("Fantom", "OO"), Pair("Clojure", "Functional"), Pair("Java", "OO") ]

    sorted := pairs.dup // make a copy of original list 
    sorted.sort |Pair a, Pair b -> Int|  // sort using custom comparator
    {
      a.name <=> b.name
    }
    echo ("Started with : " + pairs.join(" "))
    echo ("Finished with: " + sorted.join(" "))
  }
}

Fortran

Works with: Fortran version 90 and later

Standard Fortran has no built-in sort function although some compilers add them. The following example uses an insertion sort.

PROGRAM EXAMPLE
  IMPLICIT NONE  

  TYPE Pair
    CHARACTER(6) :: name
    CHARACTER(1) :: value
  END TYPE Pair

  TYPE(Pair) :: rcc(10), temp
  INTEGER :: i, j

  rcc(1) = Pair("Black", "0")
  rcc(2) = Pair("Brown", "1")
  rcc(3) = Pair("Red", "2")
  rcc(4) = Pair("Orange", "3")
  rcc(5) = Pair("Yellow", "4") 
  rcc(6) = Pair("Green", "5")
  rcc(7) = Pair("Blue", "6")
  rcc(8) = Pair("Violet", "7")
  rcc(9) = Pair("Grey", "8")
  rcc(10) = Pair("White", "9")

  DO i = 2, SIZE(rcc)
     j = i - 1
     temp = rcc(i)
        DO WHILE (j>=1 .AND. LGT(rcc(j)%name, temp%name))
           rcc(j+1) = rcc(j)
           j = j - 1
        END DO
     rcc(j+1) = temp
  END DO

  WRITE (*,"(2A6)") rcc

END PROGRAM EXAMPLE

Output

Black      0
Blue       6
Brown      1
Green      5
Grey       8
Orange     3
Red        2
Violet     7
White      9
Yellow     4

FreeBASIC

' FB 1.05.0 Win64

Type Pair
  As String name, value
  Declare Constructor(name_ As String, value_ As String)
  Declare Operator Cast() As String
End Type

Constructor Pair(name_ As String, value_ As String)
  name  = name_
  value = value_
End Constructor

Operator Pair.Cast() As String
  Return "[" + name + ", " + value + "]"
End Operator

' selection sort, quick enough for sorting small number of pairs
Sub sortPairsByName(p() As Pair)
  Dim As Integer i, j, m
  For i = LBound(p) To UBound(p) - 1
    m = i
    For j = i + 1 To UBound(p)
      If p(j).name < p(m).name Then m = j
    Next j
    If m <> i Then Swap p(i), p(m)
  Next i
End Sub

Dim As Pair pairs(1 To 4) = _
{ _
  Pair("grass", "green"), _ 
  Pair("snow", "white" ), _
  Pair("sky", "blue"),    _
  Pair("cherry", "red")   _
}

Print "Before sorting :"
For i As Integer = 1 To 4
  Print Tab(3); pairs(i)
Next

sortPairsByName pairs()

Print
Print "After sorting by name :"
For i As Integer = 1 To 4
  Print Tab(3); pairs(i)
Next

Print
Print "Press any key to quit"
Sleep
Output:
Before sorting :
  [grass, green]
  [snow, white]
  [sky, blue]
  [cherry, red]

After sorting by name :
  [cherry, red]
  [grass, green]
  [sky, blue]
  [snow, white]

Frink

Frink's lexicalCompare[a, b, language] function can sort strings in a lexicographically correct way for many human languages by specifying a language specifier like "da" for Danish. This allows sort routines to magically work correctly for many human languages.

class Pair
{
   var name
   var value
   
   new[name is string, value is string] :=
   {
      this.name = name
      this.value = value
   }
}

a = [new Pair["one", "1"], new Pair["two", "2"], new Pair["three", "3"]]
sort[a, {|a,b| lexicalCompare[a.name, b.name]}]
Output:
[Pair
{
   name = one
   value = 1
}
, Pair
{
   name = three
   value = 3
}
, Pair
{
   name = two
   value = 2
}
]

Fōrmulæ

Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.

Programs in Fōrmulæ are created/edited online in its website.

In this page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.

Solution

In the following example, it is assumed that the key is the first element of each pair.

Go

package main

import (
    "fmt"
    "sort"
)

type pair struct {
    name, value string
}
type csArray []pair

// three methods satisfy sort.Interface
func (a csArray) Less(i, j int) bool { return a[i].name < a[j].name }
func (a csArray) Len() int           { return len(a) }
func (a csArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

var x = csArray{
    pair{"joe", "120"},
    pair{"foo", "31"},
    pair{"bar", "251"},
}

func main() {
    sort.Sort(x)
    for _, p := range x {
        fmt.Printf("%5s: %s\n", p.name, p.value)
    }
}

Groovy

class Holiday {
    def date
    def name
    Holiday(dateStr, name) { this.name = name; this.date = format.parse(dateStr) }
    String toString() { "${format.format date}: ${name}" }
    static format = new java.text.SimpleDateFormat("yyyy-MM-dd")
}

def holidays = [ new Holiday("2009-12-25", "Christmas Day"),
                 new Holiday("2009-04-22", "Earth Day"),
                 new Holiday("2009-09-07", "Labor Day"),
                 new Holiday("2009-07-04", "Independence Day"),
                 new Holiday("2009-10-31", "Halloween"),
                 new Holiday("2009-05-25", "Memorial Day"),
                 new Holiday("2009-03-14", "PI Day"),
                 new Holiday("2009-01-01", "New Year's Day"),
                 new Holiday("2009-12-31", "New Year's Eve"),
                 new Holiday("2009-11-26", "Thanksgiving"),
                 new Holiday("2009-02-14", "St. Valentine's Day"),
                 new Holiday("2009-03-17", "St. Patrick's Day"),
                 new Holiday("2009-01-19", "Martin Luther King Day"),
                 new Holiday("2009-02-16", "President's Day") ]

holidays.sort { x, y -> x.date <=> y.date }
holidays.each { println it }

Output:

2009-01-01: New Year's Day
2009-01-19: Martin Luther King Day
2009-02-14: St. Valentine's Day
2009-02-16: President's Day
2009-03-14: PI Day
2009-03-17: St. Patrick's Day
2009-04-22: Earth Day
2009-05-25: Memorial Day
2009-07-04: Independence Day
2009-09-07: Labor Day
2009-10-31: Halloween
2009-11-26: Thanksgiving
2009-12-25: Christmas Day
2009-12-31: New Year's Eve

Haskell

import Data.List
import Data.Function (on)

data Person =
  P String
    Int
  deriving (Eq)

instance Show Person where
  show (P name val) = "Person " ++ name ++ " with value " ++ show val

instance Ord Person where
  compare (P a _) (P b _) = compare a b

pVal :: Person -> Int
pVal (P _ x) = x

people :: [Person]
people = [P "Joe" 12, P "Bob" 8, P "Alice" 9, P "Harry" 2]


main :: IO ()
main = do
  mapM_ print $ sort people
  putStrLn []
  mapM_ print $ sortBy (on compare pVal) people
Output:
Person Alice with value 9
Person Bob with value 8
Person Harry with value 2
Person Joe with value 12

Person Harry with value 2
Person Bob with value 8
Person Alice with value 9
Person Joe with value 12

More generally, sortBy takes any (a -> a -> Ordering) function as its first argument. A function of this kind can be derived from a simpler (b -> a) function using the higher order comparing function.

To sort a list of triples by the third element, for example:

import Data.Ord (comparing)
import Data.List (sortBy)

xs :: [(String, String, Int)]
xs =
  zip3
    (words "Richard John Marvin Alan Maurice James")
    (words "Hamming McCarthy Minskey Perlis Wilkes Wilkinson")
    [1915, 1927, 1926, 1922, 1913, 1919]

main :: IO ()
main = mapM_ print $ sortBy (comparing (\(_, _, y) -> y)) xs
Output:
("Maurice","Wilkes",1913)
("Richard","Hamming",1915)
("James","Wilkinson",1919)
("Alan","Perlis",1922)
("Marvin","Minskey",1926)
("John","McCarthy",1927)

Icon and Unicon

The built-in procedure sortf will sort a list by the field in a records.

record star(name,HIP)

procedure main()

Ori := [ star("Betelgeuse",27989),
         star("Rigel",24436),
         star("Belatrix", 25336),
         star("Alnilam",26311) ]

write("Some Orion stars by HIP#")
every write( (x := !sortf(Ori,2)).name, " HIP ",x.HIP)
end

Sample output:

Some Orion stars by HIP#
Rigel HIP 24436
Belatrix HIP 25336
Alnilam HIP 26311
Betelgeuse HIP 27989

J

The function /: sorts anything (its left argument) based on the keys supplied in its right argument. For example:

   names =: ;: 'Perlis Wilkes Hamming Minsky Wilkinson McCarthy'
   values=: ;: 'Alan Maurice Richard Marvin James John'
   pairs =: values ,. names
   pairs /: names
+-------+---------+
|Richard|Hamming  |
+-------+---------+
|John   |McCarthy |
+-------+---------+
|Marvin |Minsky   |
+-------+---------+
|Alan   |Perlis   |
+-------+---------+
|Maurice|Wilkes   |
+-------+---------+
|James  |Wilkinson|
+-------+---------+

Alternatively, J's cross operator will use the same values for both the left and right arguments for /: but, in this case, /:~ is not desirable because that would have us sorting on the values (the first column) and only using the second column for equal names (none of which appear, here).

Java

import java.util.Arrays;
import java.util.Comparator;

public class SortComp {
    public static class Pair {
        public String name;
        public String value;
        public Pair(String n, String v) {
            name = n;
            value = v;
        }
    }

    public static void main(String[] args) {
        Pair[] pairs = {new Pair("06-07", "Ducks"), new Pair("00-01", "Avalanche"),
            new Pair("02-03", "Devils"), new Pair("01-02", "Red Wings"),
            new Pair("03-04", "Lightning"), new Pair("04-05", "lockout"),
            new Pair("05-06", "Hurricanes"), new Pair("99-00", "Devils"),
            new Pair("07-08", "Red Wings"), new Pair("08-09", "Penguins")};

        sortByName(pairs);
        for (Pair p : pairs) {
            System.out.println(p.name + " " + p.value);
        }
    }

    public static void sortByName(Pair[] pairs) {
        Arrays.sort(pairs, new Comparator<Pair>() {
            public int compare(Pair p1, Pair p2) {
                return p1.name.compareTo(p2.name);
            }
        });
    }
}

Output:

00-01 Avalanche
01-02 Red Wings
02-03 Devils
03-04 Lightning
04-05 lockout
05-06 Hurricanes
06-07 Ducks
07-08 Red Wings
08-09 Penguins
99-00 Devils

In Java 8, we can write the above using a lambda:

Works with: Java version 8+
    public static void sortByName(Pair[] pairs) {
        Arrays.sort(pairs, (p1, p2) -> p1.name.compareTo(p2.name));
    }

We can further use Comparator.comparing() to construct the comparator from a "key" function:

Works with: Java version 8+
    public static void sortByName(Pair[] pairs) {
        Arrays.sort(pairs, Comparator.comparing(p -> p.name));
    }

JavaScript

ES5

var arr = [
  {id: 3, value: "foo"},
  {id: 2, value: "bar"},
  {id: 4, value: "baz"},
  {id: 1, value: 42},
  {id: 5, something: "another string"} // Works with any object declaring 'id' as a number.
];
arr = arr.sort(function(a, b) {return a.id - b.id}); // Sort with comparator checking the id.

ES6

(() => {
    'use strict';

    // GENERIC FUNCTIONS FOR COMPARISONS

    // compare :: a -> a -> Ordering
    const compare = (a, b) => a < b ? -1 : (a > b ? 1 : 0);

    // on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
    const on = (f, g) => (a, b) => f(g(a), g(b));

    // flip :: (a -> b -> c) -> b -> a -> c
    const flip = f => (a, b) => f.apply(null, [b, a]);

    // arrayCopy :: [a] -> [a]
    const arrayCopy = (xs) => xs.slice(0);

    // show :: a -> String
    const show = x => JSON.stringify(x, null, 2);


    // TEST
    const xs = [{
        name: 'Shanghai',
        pop: 24.2
    }, {
        name: 'Karachi',
        pop: 23.5
    }, {
        name: 'Beijing',
        pop: 21.5
    }, {
        name: 'Sao Paulo',
        pop: 24.2
    }, {
        name: 'Dhaka',
        pop: 17.0
    }, {
        name: 'Delhi',
        pop: 16.8
    }, {
        name: 'Lagos',
        pop: 16.1
    }]

    // population :: Dictionary -> Num
    const population = x => x.pop;

    // name :: Dictionary -> String
    const name = x => x.name;

    return show({
        byPopulation: arrayCopy(xs)
            .sort(on(compare, population)),
        byDescendingPopulation: arrayCopy(xs)
            .sort(on(flip(compare), population)),
        byName: arrayCopy(xs)
            .sort(on(compare, name)),
        byDescendingName: arrayCopy(xs)
            .sort(on(flip(compare), name))
    });
})();
Output:
{
  "byPopulation": [
    {
      "name": "Lagos",
      "pop": 16.1
    },
    {
      "name": "Delhi",
      "pop": 16.8
    },
    {
      "name": "Dhaka",
      "pop": 17
    },
    {
      "name": "Beijing",
      "pop": 21.5
    },
    {
      "name": "Karachi",
      "pop": 23.5
    },
    {
      "name": "Shanghai",
      "pop": 24.2
    },
    {
      "name": "Sao Paulo",
      "pop": 24.2
    }
  ],
  "byDescendingPopulation": [
    {
      "name": "Shanghai",
      "pop": 24.2
    },
    {
      "name": "Sao Paulo",
      "pop": 24.2
    },
    {
      "name": "Karachi",
      "pop": 23.5
    },
    {
      "name": "Beijing",
      "pop": 21.5
    },
    {
      "name": "Dhaka",
      "pop": 17
    },
    {
      "name": "Delhi",
      "pop": 16.8
    },
    {
      "name": "Lagos",
      "pop": 16.1
    }
  ],
  "byName": [
    {
      "name": "Beijing",
      "pop": 21.5
    },
    {
      "name": "Delhi",
      "pop": 16.8
    },
    {
      "name": "Dhaka",
      "pop": 17
    },
    {
      "name": "Karachi",
      "pop": 23.5
    },
    {
      "name": "Lagos",
      "pop": 16.1
    },
    {
      "name": "Sao Paulo",
      "pop": 24.2
    },
    {
      "name": "Shanghai",
      "pop": 24.2
    }
  ],
  "byDescendingName": [
    {
      "name": "Shanghai",
      "pop": 24.2
    },
    {
      "name": "Sao Paulo",
      "pop": 24.2
    },
    {
      "name": "Lagos",
      "pop": 16.1
    },
    {
      "name": "Karachi",
      "pop": 23.5
    },
    {
      "name": "Dhaka",
      "pop": 17
    },
    {
      "name": "Delhi",
      "pop": 16.8
    },
    {
      "name": "Beijing",
      "pop": 21.5
    }
  ]
}

jq

In this section we will focus on JSON objects since the task description mentions keys. As an example, we will use this array:

def example:
 [
  {"name": "Joe", "value": 3},
  {"name": "Bill", "value": 4},
  {"name": "Alice", "value": 20},
  {"name": "Harry", "value": 3}
 ];

Using sort_by builtin

jq's sort_by builtin can be used to sort by the value of a given key (whether or not it is a string), so we will first use that.

# To sort the array:
# example | sort_by(.name)

# To abbreviate the results, we will just show the names after sorting:

example | sort_by(.name) | map( .name )
Output:
$ jq -n -c -f Sort_an_array_of_composite_structures.jq
["Alice","Bill","Harry","Joe"]

Using quicksort(cmp)

sort_by(f) can easily be implemented using quicksort(cmp) as defined at Sorting_Using_a_Custom_Comparator#jq as follows:

def quicksort_by(f): quicksort( (.[0]|f) <= (.[1]|f) );

Example:

example | quicksort_by(.name) | map( .name )
Output:

As above.

Julia

Works with: Julia version 0.6
lst = Pair[Pair("gold", "shiny"),
           Pair("neon", "inert"),
           Pair("sulphur", "yellow"),
           Pair("iron", "magnetic"),
           Pair("zebra", "striped"),
           Pair("star", "brilliant"),
           Pair("apple", "tasty"),
           Pair("ruby", "red"),
           Pair("dice", "random"),
           Pair("coffee", "stimulating"),
           Pair("book", "interesting")]

println("The original list: \n - ", join(lst, "\n - "))
sort!(lst; by=first)
println("\nThe list, sorted by name: \n - ", join(lst, "\n - "))
sort!(lst; by=last)
println("\nThe list, sorted by value: \n - ", join(lst, "\n - "))
Output:
The original list: 
 - "gold"=>"shiny"
 - "neon"=>"inert"
 - "sulphur"=>"yellow"
 - "iron"=>"magnetic"
 - "zebra"=>"striped"
 - "star"=>"brilliant"
 - "apple"=>"tasty"
 - "ruby"=>"red"
 - "dice"=>"random"
 - "coffee"=>"stimulating"
 - "book"=>"interesting"

The list, sorted by name: 
 - "apple"=>"tasty"
 - "book"=>"interesting"
 - "coffee"=>"stimulating"
 - "dice"=>"random"
 - "gold"=>"shiny"
 - "iron"=>"magnetic"
 - "neon"=>"inert"
 - "ruby"=>"red"
 - "star"=>"brilliant"
 - "sulphur"=>"yellow"
 - "zebra"=>"striped"

The list, sorted by value: 
 - "star"=>"brilliant"
 - "neon"=>"inert"
 - "book"=>"interesting"
 - "iron"=>"magnetic"
 - "dice"=>"random"
 - "ruby"=>"red"
 - "gold"=>"shiny"
 - "coffee"=>"stimulating"
 - "zebra"=>"striped"
 - "apple"=>"tasty"
 - "sulphur"=>"yellow"

Kotlin

// version 1.1

data class Employee(val name: String, var category: String) : Comparable<Employee> {
    override fun compareTo(other: Employee) = this.name.compareTo(other.name)
}

fun main(args: Array<String>) {
    val employees = arrayOf(
        Employee("David", "Manager"),
        Employee("Alice", "Sales"),
        Employee("Joanna", "Director"),
        Employee("Henry", "Admin"),
        Employee("Tim", "Sales"),
        Employee("Juan", "Admin")
    )
    employees.sort()
    for ((name, category) in employees) println("${name.padEnd(6)} : $category")
}
Output:
Alice  : Sales
David  : Manager
Henry  : Admin
Joanna : Director
Juan   : Admin
Tim    : Sales

Lambdatalk

{def H.sort
 {def H.sort.i
  {lambda {:f :x :a}
   {if {A.empty? :a}
    then {A.new :x}
    else {if {:f :x {A.first :a}}
    then {A.addfirst! :x :a}
    else {A.addfirst! {A.first :a} {H.sort.i :f :x {A.rest :a}}} }}}}
 {def H.sort.r
  {lambda {:f :a1 :a2}
   {if {A.empty? :a1}
    then :a2 
    else {H.sort.r :f {A.rest :a1} {H.sort.i :f {A.first :a1} :a2}} }}}
 {lambda {:f :a}
  {H.sort.r :f :a {A.new}} }}
-> H.sort

{def H.display
 {lambda {:h}
  {table
   {tr {S.map {{lambda {:h :i} {td {car {A.get :i :h}}}} :h}
              {S.serie 0 {- {A.length :h} 1}}}}
   {tr {S.map {{lambda {:h :i} {td {cdr {A.get :i :h}}}} :h}
              {S.serie 0 {- {A.length :h} 1}}}}
}}}
-> H.display

1) an array of pairs:
{def H {A.new {cons Joe 5531}
              {cons Adam 2341}
              {cons Bernie 122} 
              {cons Walter 1234}
              {cons David 19}}}
-> H

2) display sorted by names:
{H.display
 {H.sort {lambda {:a :b} {< {lexicographic {car :a} {car :b}} 0}} {H}}}
-> 
Adam 	Bernie 	David 	Joe 	Walter
 2341 	122 	19 	5531 	1234

3) display sorted by values:
{H.display
 {H.sort {lambda {:a :b} {< {cdr :a} {cdr :b}}} {H}}}
-> 
David 	Bernie 	Walter 	Adam 	Joe
 19 	122 	1234 	2341 	5531

Liberty BASIC

NB LB sorts in a non standard order. See http://libertybasicbugs.wikispaces.com/Comparison+of+characters+and+strings+is+not+ASCII+based
The method used here to simulate a compound structure can only hold pairs of terms, since LB arrays ar 1D or 2D. More complicated associated arrays could be stored in delimiter-separated string arrays.

N =20
dim IntArray$( N, 2)

print "Original order"
for i =1 to N
    name$ =mid$( "SortArrayOfCompositeStructures", int( 25 *rnd( 1)), 1 +int( 4 *rnd( 1)))
    IntArray$( i, 1) =name$
    print name$,
    t$ =str$( int( 1000 *rnd( 1)))
    IntArray$( i, 2) =t$
    print t$
next i

sort IntArray$(), 1, N, 1
print "Sorted by name"  ' (  we specified column 1)
for i =1 to N
    print IntArray$( i, 1), IntArray$( i, 2)
next i

Lua

function sorting( a, b ) 
    return a[1] < b[1] 
end
 
tab = { {"C++", 1979}, {"Ada", 1983}, {"Ruby", 1995}, {"Eiffel", 1985} }

table.sort( tab, sorting )
for _, v in ipairs( tab ) do 
    print( unpack(v) ) 
end

M2000 Interpreter

Checkit do exactly task need: make pairs as groups of name and value_ (note _ used because value used for other purpose in a group definition), make a Quick group from class Quick, pass a new lambda for comparing items, and pass array with objects to sort in quicksort function of Quick group. Keys no need to be unique.

Checkit2 make an inventory with keys and values, then sort them (internal use Quicksort, and keys must be unique)

Checkit3 same as CheckIt3 except values are groups, which now have only a x as value, but we can add more.

Module CheckIt {
      Flush ' empty stack of values
      Class Quick {
      Private:
            partition=lambda-> {
                  Read &A(), p, r : i = p-1 : x=A(r)
                  For j=p to r-1 {If .LE(A(j), x) Then i++:Swap A(i),A(j)
                  } : Swap A(i+1), A(r) :  Push  i+2, i 
            }
      Public:
            LE=Lambda->Number<=Number
            Module ForStrings {
                  .partition<=lambda-> {
                        Read &a$(), p, r : i = p-1 : x$=a$(r)
                        For j=p to r-1 {If a$(j)<= x$ Then i++:Swap a$(i),a$(j)
                        } : Swap a$(i+1), a$(r) : Push i+2, i
                  }
            }
            Function quicksort {
                 Read ref$
                 {
                         loop : If Stackitem() >= Stackitem(2) Then Drop 2 : if  empty then {Break} else continue
                         over 2,2 : call .partition(ref$) :shift 3 
                 }
            }
      }
      Quick=Quick()
      Quick.LE=lambda (a, b)->{
            =a.name$<=b.name$
      }
      Data "Joe",   5531
      Data "Adam", 2341
      Data "Bernie", 122
      Data "Walter", 1234
      Data "David",  19
      Class pair {
            name$
            value_
      }
      Document Doc$={Unsorted Pairs:
      }
      Dim A(1 to 5)=pair()
      For i=1 to 5 {
            For A(i) {
                  Read .name$, .value_
                  Doc$=Format$("{0}, {1}", .name$, .value_)+{
                  }
            }
      }
      
      Call Quick.quicksort(&A(),1, 5)
      Doc$={
            Sorted Pairs
            }
      k=Each(A())
      While k {
            getone=array(k)
            For getone {
                              Doc$=Format$("{0}, {1}", .name$, .value_)+{
                              }
            }
      }
      Report Doc$
      Clipboard Doc$
}
Checkit
module Checkit2 {
      Inventory Alfa="Joe":=5531, "Adam":=2341, "Bernie":=122
      Append Alfa, "Walter":=1234, "David":=19
      Sort Alfa
      k=Each(Alfa)
      While k {
            Print eval$(Alfa, k^), Eval(k)
      }
}
Checkit2
module Checkit3 {
      class any {
             x
            class:
            Module any (.x) {}
      }
      Inventory Alfa="Joe":=any(5531), "Adam":=any(2341), "Bernie":=any(122)
      Append Alfa, "Walter":=any(1234), "David":=any(19)
      Sort Alfa
      k=Each(Alfa)
      While k {
            \\ k^ is the index number by k cursor
            \\ Alfa("joe") return object
            \\ Alfa(0!) return first element object
            \\ Alfa(k^!) return (k^) objext
            Print eval$(Alfa, k^),  Alfa(k^!).x
      }
}
Checkit3
Output:

From Checkit (checkit2 and checkit3 show exact sorted inventories)

Unsorted Pairs:
Joe, 5531
Adam, 2341
Bernie, 122
Walter, 1234
David, 19

Sorted Pairs
Adam, 2341
Bernie, 122
David, 19
Joe, 5531
Walter, 1234

Mathematica/Wolfram Language

events = {{"2009-12-25", "Christmas Day"}, {"2009-04-22", 
    "Earth Day"}, {"2009-09-07", "Labor Day"}, {"2009-07-04", 
    "Independence Day"}, {"2009-10-31", "Halloween"}, {"2009-05-25", 
    "Memorial Day"}, {"2009-03-14", "PI Day"}, {"2009-01-01", 
    "New Year's Day"}, {"2009-12-31", 
    "New Year's Eve"}, {"2009-11-26", "Thanksgiving"}, {"2009-02-14", 
    "St. Valentine's Day"}, {"2009-03-17", 
    "St. Patrick's Day"}, {"2009-01-19", 
    "Martin Luther King Day"}, {"2009-02-16", "President's Day"}};
date = 1;
name = 2;
SortBy[events, #[[name]] &] // Grid
SortBy[events, #[[date]] &] // Grid

gives back:

2009-12-25 Christmas Day
2009-04-22 Earth Day
2009-10-31 Halloween
2009-07-04 Independence Day
2009-09-07 Labor Day
2009-01-19 Martin Luther King Day
2009-05-25 Memorial Day
2009-01-01 New Year's Day
2009-12-31 New Year's Eve
2009-03-14 PI Day
2009-02-16 President's Day
2009-03-17 St. Patrick's Day
2009-02-14 St. Valentine's Day
2009-11-26 Thanksgiving


2009-01-01 New Year's Day
2009-01-19 Martin Luther King Day
2009-02-14 St. Valentine's Day
2009-02-16 President's Day
2009-03-14 PI Day
2009-03-17 St. Patrick's Day
2009-04-22 Earth Day
2009-05-25 Memorial Day
2009-07-04 Independence Day
2009-09-07 Labor Day
2009-10-31 Halloween
2009-11-26 Thanksgiving
2009-12-25 Christmas Day
2009-12-31 New Year's Eve

MAXScript

fn keyCmp comp1 comp2 =
(
    case of
    (
        (comp1[1] > comp2[1]):	1
        (comp1[1] < comp2[1]):	-1
        default:		0
    )
)

people = #(#("joe", 39), #("dave", 37), #("bob", 42))
qsort people keyCmp
print people

NetRexx

/* NetRexx */
options replace format comments java crossref symbols nobinary

-- =============================================================================
class RSortCompsiteStructure public

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method main(args = String[]) public static
    places = [ -
      PairBean('London',     'UK'), PairBean('New York',   'US') -
    , PairBean('Boston',     'US'), PairBean('Washington', 'US') -
    , PairBean('Washington', 'UK'), PairBean("Birmingham", 'US') -
    , PairBean("Birmingham", 'UK'), PairBean("Boston",     'UK') -
    ]
    say displayArray(places)
    Arrays.sort(places, PairComparator())
    say displayArray(places)
    return
  
  method displayArray(harry = PairBean[]) constant
    disp = ''
    loop elmt over harry
      disp = disp','elmt
      end elmt
    return '['disp.substr(2)']' -- trim leading comma

-- =============================================================================
class RSortCompsiteStructure.PairBean
  properties indirect
    name
    value
  method PairBean(name_, value_) public
    setName(name_)
    setValue(value_)
    return
  method toString() public returns String
    return '('getName()','getValue()')'

-- =============================================================================
class RSortCompsiteStructure.PairComparator implements Comparator
  method compare(lft = Object, rgt = Object) public binary returns int
    cRes = int
    if lft <= RSortCompsiteStructure.PairBean, rgt <= RSortCompsiteStructure.PairBean then do
      lName = String (RSortCompsiteStructure.PairBean lft).getName()
      rName = String (RSortCompsiteStructure.PairBean rgt).getName()
      cRes = lName.compareTo(rName)
      if cRes == 0 then do
        lVal = String (RSortCompsiteStructure.PairBean lft).getValue()
        rVal = String (RSortCompsiteStructure.PairBean rgt).getValue()
        cRes = lVal.compareTo(rVal)
        end
      end
    else signal IllegalArgumentException('Arguments must be of type PairBean')
    return cRes

Output:

[(London,UK),(New York,US),(Boston,US),(Washington,US),(Washington,UK),(Birmingham,US),(Birmingham,UK),(Boston,UK)]
[(Birmingham,UK),(Birmingham,US),(Boston,UK),(Boston,US),(London,UK),(New York,US),(Washington,UK),(Washington,US)]

Nim

import algorithm, sugar

var people = @{"joe": 120, "foo": 31, "bar": 51}
sort(people, (x,y) => cmp(x[0], y[0]))
echo people
Output:
@[("bar", 51), ("foo", 31), ("joe", 120)]

Objeck

use Collection;

class Entry implements Compare {
  @name : String;
  @value : Float;

  New(name : String, value : Float) {
    @name := name;
    @value := value;
  }

  method : public : Compare(rhs : Compare) ~ Int  {
    return @name->Compare(rhs->As(Entry)->GetName());
  }

  method : public : GetName() ~ String {
    return @name;
  }
  
  method : public : HashID() ~ Int {
    return @name->HashID();
  }

  method : public : ToString() ~ String {
    return "name={$@name}, value={$@value}";
  }
}

class Sorter {
  function : Main(args : String[]) ~ Nil {
    entries := CompareVector->New();
    entries->AddBack(Entry->New("Krypton", 83.798));
    entries->AddBack(Entry->New("Beryllium", 9.012182));
    entries->AddBack(Entry->New("Silicon", 28.0855));
    entries->AddBack(Entry->New("Cobalt", 58.933195)); 
    entries->AddBack(Entry->New("Selenium", 78.96));
    entries->AddBack(Entry->New("Germanium", 72.64));

    entries->Sort();
    each(i : entries) {
      entries->Get(i)->As(Entry)->ToString()->PrintLine();
    };
  }
}
name=Beryllium, value=9.12
name=Cobalt, value=58.934
name=Germanium, value=72.640
name=Krypton, value=83.798
name=Selenium, value=78.960
name=Silicon, value=28.85

Objective-C

@interface Pair : NSObject {
    NSString *name;
    NSString *value;
}
+(instancetype)pairWithName:(NSString *)n value:(NSString *)v;
-(instancetype)initWithName:(NSString *)n value:(NSString *)v;
-(NSString *)name;
-(NSString *)value;
@end

@implementation Pair
+(instancetype)pairWithName:(NSString *)n value:(NSString *)v {
    return [[self alloc] initWithName:n value:v];
}
-(instancetype)initWithName:(NSString *)n value:(NSString *)v {
    if ((self = [super init])) {
        name = n;
        value = v;
    }
    return self;
}
-(NSString *)name { return name; }
-(NSString *)value { return value; }
-(NSString *)description {
    return [NSString stringWithFormat:@"< %@ -> %@ >", name, value];
}
@end

int main() {
    @autoreleasepool {

        NSArray *pairs = @[
                       [Pair pairWithName:@"06-07" value:@"Ducks"],
                       [Pair pairWithName:@"00-01" value:@"Avalanche"],
                       [Pair pairWithName:@"02-03" value:@"Devils"],
                       [Pair pairWithName:@"01-02" value:@"Red Wings"],
                       [Pair pairWithName:@"03-04" value:@"Lightning"],
                       [Pair pairWithName:@"04-05" value:@"lockout"],
                       [Pair pairWithName:@"05-06" value:@"Hurricanes"],
                       [Pair pairWithName:@"99-00" value:@"Devils"],
                       [Pair pairWithName:@"07-08" value:@"Red Wings"],
                       [Pair pairWithName:@"08-09" value:@"Penguins"]];

        // optional 3rd arg: you can also specify a selector to compare the keys
        NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

        // it takes an array of sort descriptors, and it will be ordered by the
        // first one, then if it's a tie by the second one, etc.
        NSArray *sorted = [pairs sortedArrayUsingDescriptors:@[sd]];
        NSLog(@"%@", sorted);

    }

    return 0;
}

OCaml

# let people = [("Joe", 12); ("Bob", 8); ("Alice", 9); ("Harry", 2)];;
val people : (string * int) list =
  [("Joe", 12); ("Bob", 8); ("Alice", 9); ("Harry", 2)]
# let sortedPeopleByVal = List.sort (fun (_, v1) (_, v2) -> compare v1 v2) people;;
val sortedPeopleByVal : (string * int) list =
  [("Harry", 2); ("Bob", 8); ("Alice", 9); ("Joe", 12)]

Oforth

[["Joe",5531], ["Adam",2341], ["Bernie",122], ["David",19]] sortBy(#first) println
Output:
[[Adam, 2341], [Bernie, 122], [David, 19], [Joe, 5531]]

Ol

(import (scheme char))

(define (comp a b)
   (string-ci<? (a 'name #f) (b 'name #f)))

(for-each print
   (sort comp (list
      { 'name "David"
        'value "Manager" }
      { 'name "Alice"
        'value "Sales" }
      { 'name "Joanna"
        'value "Director" }
      { 'name "Henry"
        'value "Admin" }
      { 'name "Tim"
        'value "Sales" }
      { 'name "Juan"
        'value "Admin" })))
Output:
#ff((name . Alice) (value . Sales))
#ff((name . David) (value . Manager))
#ff((name . Henry) (value . Admin))
#ff((name . Joanna) (value . Director))
#ff((name . Juan) (value . Admin))
#ff((name . Tim) (value . Sales))

ooRexx

a = .array~new

a~append(.pair~new("06-07", "Ducks"))
a~append(.pair~new("00-01", "Avalanche"))
a~append(.pair~new("02-03", "Devils"))
a~append(.pair~new("01-02", "Red Wings"))
a~append(.pair~new("03-04", "Lightning"))
a~append(.pair~new("04-05", "lockout"))
a~append(.pair~new("05-06", "Hurricanes"))
a~append(.pair~new("99-00", "Devils"))
a~append(.pair~new("07-08", "Red Wings"))
a~append(.pair~new("08-09", "Penguins"))

b = a~copy   -- make a copy before sorting
b~sort
say "Sorted using direct comparison"
do pair over b
   say pair
end

c = a~copy
-- this uses a custom comparator instead
c~sortWith(.paircomparator~new)
say
say "Sorted using a comparator (inverted)"
do pair over c
   say pair
end

-- a name/value mapping class that directly support the sort comparisons
::class pair inherit comparable
::method init
  expose name value
  use strict arg name, value

::attribute name
::attribute value

::method string
  expose name value
  return name "=" value

-- the compareto method is a requirement brought in
-- by the
::method compareto
  expose name
  use strict arg other
  return name~compareto(other~name)

-- a comparator that shows an alternate way of sorting
::class pairComparator subclass comparator
::method compare
  use strict arg left, right
  -- perform the comparison on the names
  return -left~name~compareTo(right~name)

Output:

Sorted using direct comparison
00-01 = Avalanche
01-02 = Red Wings
02-03 = Devils
03-04 = Lightning
04-05 = lockout
05-06 = Hurricanes
06-07 = Ducks
07-08 = Red Wings
08-09 = Penguins
99-00 = Devils

Sorted using a comparator (inverted)
99-00 = Devils
08-09 = Penguins
07-08 = Red Wings
06-07 = Ducks
05-06 = Hurricanes
04-05 = lockout
03-04 = Lightning
02-03 = Devils
01-02 = Red Wings
00-01 = Avalanche

Oz

declare
  People = [person(name:joe value:3)
            person(name:bill value:4)
            person(name:alice value:20)
            person(name:harry value:3)]

  SortedPeople = {Sort People
                  fun {$ P1 P2}
                     P1.name < P2.name
                  end
                 }
in
  {ForAll SortedPeople Show}

PARI/GP

The flag "2" means that lexicographic sorting is to be used; the "1" means that the array is to be sorted using the first element of each constituent vector.

vecsort([["name", "value"],["name2", "value2"]], 1, 2)

Pascal

mergesort example sorts an array of record http://rosettacode.org/wiki/Sorting_algorithms/Merge_sort#improvement

Perl

Sort by name using cmp to compare strings:

@people = (['joe', 120], ['foo', 31], ['bar', 51]);
@people = sort { $a->[0] cmp $b->[0] } @people;

Sort by number using <=> to compare numbers:

@people = (['joe', 120], ['foo', 31], ['bar', 51]);
@people = sort { $a->[1] <=> $b->[1] } @people;

Phix

Library: Phix/basics

The standard sort compares the first element, then 2nd, 3rd, etc. A custom_sort or sort_columns can be used to sort by other elements.
Elements can be any mix of types, with atoms (ie ints/floats) deemed less than sequences/strings.

sequence s = {{"grass","green"},{"snow","white"},{"sky","blue"},{"cherry","red"},{0,1.2},{3.4,-1}}
 
?sort(s)
function compare_col2(sequence a, b) return compare(a[2],b[2]) end function
?custom_sort(compare_col2,s)
?sort_columns(s,{2})    -- 0.8.0+, same result as above w/o needing an explicit comparison routine
Output:
{{0,1.2},{3.4,-1},{"cherry","red"},{"grass","green"},{"sky","blue"},{"snow","white"}}
{{3.4,-1},{0,1.2},{"sky","blue"},{"grass","green"},{"cherry","red"},{"snow","white"}}
{{3.4,-1},{0,1.2},{"sky","blue"},{"grass","green"},{"cherry","red"},{"snow","white"}}

Phixmonti

include ..\Utilitys.pmt

def minverse
    reverse
enddef

getid minverse var f

( ( "grass" "green" ) ( "snow" "white" ) ( "sky" "blue" ) ( "cherry" "red" ) ( 0 1.2 ) ( 3.4 -1 ) )
dup

sort print nl

/# sorted by second component #/
f map sort f map print

PicoLisp

By default, the sort function in PicoLisp returns an ascending list (of any type)

: (sort '(("def" 456) ("abc" 789) ("ghi" 123)))
-> (("abc" 789) ("def" 456) ("ghi" 123))

To sort by a certain sub-element, the function by can be used. For example, to sort by the first element

: (by car sort '(("def" 456) ("abc" 789) ("ghi" 123)))
-> (("abc" 789) ("def" 456) ("ghi" 123))

or by the second element

: (by cadr sort '(("def" 456) ("abc" 789) ("ghi" 123)))
-> (("ghi" 123) ("def" 456) ("abc" 789))

PowerShell

Works with: PowerShell version 4.0
$list = @{
"def" = "one"
"abc" = "two"
"jkl" = "three"
"abcdef" = "four"
"ghi" = "five"
"ghijkl" = "six"
 }
 $list.GetEnumerator() | sort {-($PSItem.Name).length}, Name

Output:

Name                           Value                                                                               
----                           -----                                                                               
abcdef                         four                                                                                
ghijkl                         six                                                                                 
abc                            two                                                                                 
def                            one                                                                                 
ghi                            five                                                                                
jkl                            three                                                                                  

PureBasic

PureBasic natively supports sorting of structured data with;

  • SortStructuredArray()
  • SortStructuredList()

The on-line documentations gives a more complete picture.


Example

Structure MyPair ; Define a structured data type
  Name$
  Value.i
EndStructure

Dim People.MyPair(2)             ; Allocate some elements

People(0)\Name$ = "John"         ; Start filling them in
People(0)\Value = 100

People(1)\Name$ = "Emma"
People(1)\Value = 200

People(2)\Name$ = "Johnny"
People(2)\Value = 175

If OpenConsole()
  Define i
  ; Sort ascending by name
  SortStructuredArray(People(), #PB_Sort_Ascending, OffsetOf(MyPair\Name$), #PB_Sort_String)
  PrintN(#CRLF$+"Sorted ascending by name.")
  For i=0 To 2
    PrintN(People(i)\Name$+" - Value: "+Str(People(i)\Value))
  Next
  ; Sort descending by value
  SortStructuredArray(People(), #PB_Sort_Descending, OffsetOf(MyPair\Value), #PB_Sort_Integer)
  PrintN(#CRLF$+"Sorted descending by value.")
  For i=0 To 2
    PrintN(People(i)\Name$+" - Value: "+Str(People(i)\Value))
  Next
  ; Wait for user...
  PrintN(#CRLF$+"Press ENTER to exit"):Input()
EndIf

Outputs

Sorted ascending by name.
Emma - Value: 200
John - Value: 100
Johnny - Value: 175

Sorted descending by value.
Emma - Value: 200
Johnny - Value: 175
John - Value: 100

Python

Recent versions of Python provide the sorted() built-in that works on any iterable.

people = [('joe', 120), ('foo', 31), ('bar', 51)]
sorted(people)

Which leaves people with the value:

[('bar', 51), ('foo', 31), ('joe', 120)]


The most Pythonic (and fastest) version is to use itemgetter together with the key parameter to sort resp. sorted to perform the Decorate-sort-undecorate pattern:

from operator import itemgetter
people = [(120, 'joe'), (31, 'foo'), (51, 'bar')]
people.sort(key=itemgetter(1))

Which leaves people with the value:

[(51, 'bar'), (31, 'foo'), (120, 'joe')]

R

In R, vectors can have names associated with any of its elements. The data is taken from the Common Lisp example.

sortbyname <- function(x, ...) x[order(names(x), ...)]
x <- c(texas=68.9, ohio=87.8, california=76.2, "new york"=88.2)
sortbyname(x)
california   new york       ohio      texas 
      76.2       88.2       87.8       68.9 
sortbyname(x, decreasing=TRUE)
     texas       ohio   new york california 
      68.9       87.8       88.2       76.2

Racket

#lang racket

(define data '([Joe 5531] [Adam 2341] [Bernie 122] [Walter 1234] [David 19]))

(sort data < #:key cadr)
;; --> '((David 19) (Bernie 122) (Walter 1234) (Adam 2341) (Joe 5531))

;; Demonstrating a "key" that is not just a direct element
(sort data string<? #:key (compose1 symbol->string car))
;; --> '((Adam 2341) (Bernie 122) (David 19) (Joe 5531) (Walter 1234))

Raku

(formerly Perl 6)

Works with: rakudo version 2016.05
my class Employee {
   has Str $.name;
   has Rat $.wage;
}

my $boss     = Employee.new( name => "Frank Myers"     , wage => 6755.85 );
my $driver   = Employee.new( name => "Aaron Fast"      , wage => 2530.40 );
my $worker   = Employee.new( name => "John Dude"       , wage => 2200.00 );
my $salesman = Employee.new( name => "Frank Mileeater" , wage => 4590.12 );

my @team = $boss, $driver, $worker, $salesman;

my @orderedByName = @team.sort( *.name )».name;
my @orderedByWage = @team.sort( *.wage )».name;

say "Team ordered by name (ascending order):";
say @orderedByName.join('  ');
say "Team ordered by wage (ascending order):";
say @orderedByWage.join('  ');

this produces the following output:

Team ordered by name (ascending order): 
Aaron Fast   Frank Mileeater   Frank Myers   John Dude   
Team ordered by wage (ascending order): 
John Dude   Aaron Fast   Frank Mileeater   Frank Myers   

Note that when the sort receives a unary function, it automatically generates an appropriate comparison function based on the type of the data.

REXX

This version sorts the structure by color;   as entered (built),   the structure is ordered by value (percent).

/*REXX program sorts an array of composite structures                 */
/* (which has two classes of data).                                   */
x.=0                           /*number elements in structure (so far)*/
Call add 'tan'   , 0           /*tan    peanut M&M's are  0%  of total*/
Call add 'orange',10           /*orange    "    "     "  10%   "   "  */
Call add 'yellow',20           /*yellow    "    "     "  20%   "   "  */
Call add 'green' ,20           /*green     "    "     "  20%   "   "  */
Call add 'red'   ,20           /*red       "    "     "  20%   "   "  */
Call add 'brown' ,30           /*brown     "    "     "  30%   "   "  */
Call show 'before sort'
Say copies('¦', 70)
Call xSort
call show ' after sort'
Exit                           /*stick a fork in it, we're all done.  */
/*--------------------------------------------------------------------*/
add: Procedure Expose x.
  z=x.0+1                      /* bump the number of structure entry  */
  x.z.color=arg(1)
  x.z.pc=arg(2)                /* construct an entry of the structure */
  x.0=z
  Return
/*--------------------------------------------------------------------*/
show: Procedure Expose x.
  Do i=1 To x.0
    /* display  what     name               value.                    */
    Say right(arg(1),30) right(x.i.color,9) right(x.i.pc,4)'%'
    End
  Return
/*--------------------------------------------------------------------*/
xsort: Procedure Expose x.
  h=x.0
  Do While h>1
    h=h%2
    Do i=1 For x.0-h
      j=i
      k=h+i
      Do While x.k.color<x.j.color
        _=x.j.color                 /* swap elements.                 */
        x.j.color=x.k.color
        x.k.color=_
        _=x.j.pc
        x.j.pc=x.k.pc
        x.k.pc=_
        If h>=j Then
          Leave
        j=j-h
        k=k-h
        End
      End
    End
  Return

output   when using the (internal) default inputs:

                   before sort       tan    0%
                   before sort    orange   10%
                   before sort    yellow   20%
                   before sort     green   20%
                   before sort       red   20%
                   before sort     brown   30%
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
                    after sort     brown   30%
                    after sort     green   20%
                    after sort    orange   10%
                    after sort       red   20%
                    after sort       tan    0%
                    after sort    yellow   20%

Ring

aList= sort([:Eight = 8, :Two = 2, :Five = 5, :Nine = 9, :One = 1,
             :Three = 3, :Six = 6, :Seven = 7, :Four = 4, :Ten = 10] , 2)
for item in aList
    ? item[1] + space(10-len(item[1])) + item[2]
next
Output:
one       1
two       2
three     3
four      4
five      5
six       6
seven     7
eight     8
nine      9
ten       10

Ruby

Person = Struct.new(:name,:value) do
  def to_s; "name:#{name}, value:#{value}" end
end

list = [Person.new("Joe",3),
        Person.new("Bill",4),
        Person.new("Alice",20),
        Person.new("Harry",3)]
puts list.sort_by{|x|x.name}
puts
puts list.sort_by(&:value)
Output:
name:Alice, value:20
name:Bill, value:4
name:Harry, value:3
name:Joe, value:3

name:Joe, value:3
name:Harry, value:3
name:Bill, value:4
name:Alice, value:20

Run BASIC

sqliteconnect #mem, ":memory:"                          ' create in memory db
mem$	= "CREATE TABLE people(num integer, name text,city text)"
#mem execute(mem$)
data "1","George","Redding","2","Fred","Oregon","3","Ben","Seneca","4","Steve","Fargo","5","Frank","Houston"

for i = 1 to 5                                          ' read data and place in memory DB
 read num$ :read name$: read city$
 #mem execute("INSERT INTO people VALUES(";num$;",'";name$;"','";city$;"')")
next i
#mem execute("SELECT * FROM people ORDER BY name")      'sort by name order
WHILE  #mem hasanswer()
  #row  = #mem #nextrow()
  num   = #row num()
  name$	= #row name$()
  city$	= #row city$()
  print num;" ";name$;" ";city$
WEND
3 Ben Seneca
5 Frank Houston
2 Fred Oregon
1 George Redding
4 Steve Fargo

Rust

Translation of: Kotlin
use std::cmp::Ordering;

#[derive(Debug)]
struct Employee {
    name: String,
    category: String,
}

impl Employee {
    fn new(name: &str, category: &str) -> Self {
        Employee {
            name: name.into(),
            category: category.into(),
        }
    }
}

impl PartialEq for Employee {
    fn eq(&self, other: &Self) -> bool {
        self.name == other.name
    }
}

impl Eq for Employee {}

impl PartialOrd for Employee {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Employee {
    fn cmp(&self, other: &Self) -> Ordering {
        self.name.cmp(&other.name)
    }
}

fn main() {
    let mut employees = vec![
        Employee::new("David", "Manager"),
        Employee::new("Alice", "Sales"),
        Employee::new("Joanna", "Director"),
        Employee::new("Henry", "Admin"),
        Employee::new("Tim", "Sales"),
        Employee::new("Juan", "Admin"),
    ];
    employees.sort();
    for e in employees {
        println!("{:<6} : {}", e.name, e.category);
    }
}
Output:
Alice  : Sales
David  : Manager
Henry  : Admin
Joanna : Director
Juan   : Admin
Tim    : Sales

Scala

case class Pair(name:String, value:Double)
val input = Array(Pair("Krypton", 83.798), Pair("Beryllium", 9.012182), Pair("Silicon", 28.0855))
input.sortBy(_.name) // Array(Pair(Beryllium,9.012182), Pair(Krypton,83.798), Pair(Silicon,28.0855))

// alternative versions:
input.sortBy(struct => (struct.name, struct.value)) // additional sort field (name first, then value)
input.sortWith((a,b) => a.name.compareTo(b.name) < 0) // arbitrary comparison function

Seed7

$ include "seed7_05.s7i";

const type: pair is new struct
    var string: name is "";
    var string: value is "";
  end struct;

const func integer: compare (in pair: pair1, in pair: pair2) is
  return compare(pair1.name, pair2.name);

const func string: str (in pair: aPair) is
  return "(" <& aPair.name <& ", " <& aPair.value <& ")";

enable_output(pair);

const func pair: pair (in string: name, in string: value) is func
  result
    var pair: newPair is pair.value;
  begin
    newPair.name := name;
    newPair.value := value;
  end func;

var array pair: data is [] (
    pair("Joe",    "5531"),
    pair("Adam",   "2341"),
    pair("Bernie", "122"),
    pair("Walter", "1234"),
    pair("David",  "19"));

const proc: main is func
  local
    var pair: aPair is pair.value;
  begin
    data := sort(data);
    for aPair range data do
      writeln(aPair);
    end for;
  end func;

Output:

(Adam, 2341)
(Bernie, 122)
(David, 19)
(Joe, 5531)
(Walter, 1234)

Sidef

# Declare an array of pairs
var people = [['joe', 120], ['foo', 31], ['bar', 51]];

# Sort the array in-place by name
people.sort! {|a,b| a[0] <=> b[0] };

# Alternatively, we can use the `.sort_by{}` method
var sorted = people.sort_by { |item| item[0] };

# Display the sorted array
say people;
Output:
[["bar", 51], ["foo", 31], ["joe", 120]]

Simula

BEGIN

    CLASS COMPARABLE;;

    COMPARABLE CLASS PAIR(N,V); TEXT N,V;;

    CLASS COMPARATOR;
    VIRTUAL:
        PROCEDURE COMPARE IS
            INTEGER PROCEDURE COMPARE(A, B); REF(COMPARABLE) A, B;;
    BEGIN
    END**OF**COMPARATOR;

    COMPARATOR CLASS PAIRBYNAME;
    BEGIN
        INTEGER PROCEDURE COMPARE(A, B); REF(COMPARABLE) A, B;
        BEGIN
            COMPARE := IF A QUA PAIR.N < B QUA PAIR.N THEN -1 ELSE
                       IF A QUA PAIR.N > B QUA PAIR.N THEN +1 ELSE 0;
        END;
    END**OF**PAIRBYNAME;

    PROCEDURE BUBBLESORT(A, C); NAME A; REF(COMPARABLE) ARRAY A; REF(COMPARATOR) C;
    BEGIN
       INTEGER LOW, HIGH, I;
       BOOLEAN SWAPPED;

       PROCEDURE SWAP(I, J); INTEGER I, J;
       BEGIN
           REF(COMPARABLE) TEMP;
           TEMP :- A(I); A(I) :- A(J); A(J) :- TEMP;
       END**OF**SWAP;

       LOW := LOWERBOUND(A, 1);
       HIGH := UPPERBOUND(A, 1);
       SWAPPED := TRUE;
       WHILE SWAPPED DO
       BEGIN
           SWAPPED := FALSE;
           FOR I := LOW + 1 STEP 1 UNTIL HIGH DO
           BEGIN
               COMMENT IF THIS PAIR IS OUT OF ORDER ;
               IF C.COMPARE(A(I - 1), A(I)) > 0 THEN
               BEGIN
                   COMMENT SWAP THEM AND REMEMBER SOMETHING CHANGED ;
                   SWAP(I - 1, I);
                   SWAPPED := TRUE;
               END;
           END;
       END;
    END**OF**BUBBLESORT;

    COMMENT ** MAIN PROGRAM **;
    REF(PAIR) ARRAY A(1:5);
    INTEGER I;

    A(1) :- NEW PAIR( "JOE", "5531" );
    A(2) :- NEW PAIR( "ADAM", "2341" );
    A(3) :- NEW PAIR( "BERNIE", "122" );
    A(4) :- NEW PAIR( "WALTER", "1234" );
    A(5) :- NEW PAIR( "DAVID", "19" );

    BUBBLESORT(A, NEW PAIRBYNAME);

    FOR I:= 1 STEP 1 UNTIL 5 DO
    BEGIN OUTTEXT(A(I).N); OUTCHAR(' '); OUTTEXT(A(I).V); OUTIMAGE; END;
    OUTIMAGE;
    
END.
Output:
ADAM 2341
BERNIE 122
DAVID 19
JOE 5531
WALTER 1234

SQL

We can treat the array of data structures as a table. An order by clause in a query will sort the data.

-- setup
create table pairs (name varchar(16), value varchar(16));
insert into pairs values ('Fluffy', 'cat');
insert into pairs values ('Fido', 'dog');
insert into pairs values ('Francis', 'fish');
-- order them by name
select * from pairs order by name;
Output:
NAME             VALUE
---------------- ----------------
Fido             dog
Fluffy           cat
Francis          fish

Swift

extension Sequence {
  func sorted<Value>(
    on: KeyPath<Element, Value>,
    using: (Value, Value) -> Bool
  ) -> [Element] where Value: Comparable {
    return withoutActuallyEscaping(using, do: {using -> [Element] in
      return self.sorted(by: { using($0[keyPath: on], $1[keyPath: on]) })
    })
  }
}

struct Person {
  var name: String
  var role: String
}

let a = Person(name: "alice", role: "manager")
let b = Person(name: "bob", role: "worker")
let c = Person(name: "charlie", role: "driver")

print([c, b, a].sorted(on: \.name, using: <))
Output:
[Runner.Person(name: "alice", role: "manager"), Runner.Person(name: "bob", role: "worker"), Runner.Person(name: "charlie", role: "driver")]

Tcl

Modeling the data structure being sorted as a list (a common Tcl practice):

set people {{joe 120} {foo 31} {bar 51}}
# sort by the first element of each pair
lsort -index 0 $people

UNIX Shell

With this language, everything is a string. My list of pairs is a string where a colon ":" separates "name:value", and a newline separates different pairs. Then I can use sort -t: -k1,1 to sort the pairs by name.

list="namez:order!
name space:in
name1:sort
name:Please"

newline="
"

dumplist() {
	(
		IFS=$newline
		for pair in $list; do
			(
				IFS=:
				set -- $pair
				echo "  $1 => $2"
			)
		done
	)
}

echo "Original list:"
dumplist

list=`IFS=$newline; printf %s "$list" | sort -t: -k1,1`

echo "Sorted list:"
dumplist

Output:

Original list:
  namez => order!
  name space => in
  name1 => sort
  name => Please
Sorted list:
  name => Please
  name space => in
  name1 => sort
  namez => order!

Ursala

The built in sort operator, -<, can be parameterized by an anonymous field specification and/or a relational predicate.

#import std

#cast %sWLW

examples = 

(
   -<&l <('z','a'),('x','c'),('y','b')>,  # sorted by the left
   -<&r <('z','a'),('x','c'),('y','b')>)  # sorted by the right

output:

(
   <('x','c'),('y','b'),('z','a')>,
   <('z','a'),('y','b'),('x','c')>)

a more verbose example, showing a list of records of a user defined type sorted by a named field:

#import std

person :: name %s value %s

people =

<
   person[name: 'Marilyn Monroe',value: 'priceless'],
   person[name: 'Victor Hugo',value: 'millions'],
   person[name: 'Johnny Carson',value: 'up there']>

#cast _person%L

example = (lleq+ ~name~~)-< people

output:

<
   person[name: 'Johnny Carson',value: 'up there'],
   person[name: 'Marilyn Monroe',value: 'priceless'],
   person[name: 'Victor Hugo',value: 'millions']>

Wren

Library: Wren-sort
import "./sort" for Cmp, Sort, Comparable

class Pair is Comparable {
    construct new (name, value) {
        _name = name
        _value = value
    }

    name  { _name }
    value { _value }

    compare(other) { Cmp.string.call(_name, other.name) }

    toString { "{%(_name), %(_value)}" }
}

var pairs = [
    Pair.new("grass", "green"),
    Pair.new("snow", "white"),
    Pair.new("sky", "blue"),
    Pair.new("cherry", "red")
]

System.print("Before sorting:")
System.print("  " + pairs.join("\n  "))
Sort.insertion(pairs)
System.print("\nAfter sorting:")
System.print("  " + pairs.join("\n  "))
Output:
Before sorting:
  {grass, green}
  {snow, white}
  {sky, blue}
  {cherry, red}

After sorting:
  {cherry, red}
  {grass, green}
  {sky, blue}
  {snow, white}

XPL0

include c:\cxpl\stdlib;
char Dict(10,10);
int  Entries;

proc BSort(A, N);       \Bubble sort array A's key string into ascending order
char A;                 \address of array
int  N;                 \number of items in array (size)
int  B, I, J, T;
[B:= A;                 \B(I) accesses 32-bit pointers, not A(I) 8-bit bytes
for J:= N-1 downto 0 do
    for I:= 0 to J-1 do
        if StrCmp(A(I,1), A(I+1,1)) > 0 then
            [T:= B(I);  B(I):= B(I+1);  B(I+1):= T];    \swap pointers
];

proc AddEntry(Letter, Greek);   \Insert entry into associative array
char Letter, Greek;
[Dict(Entries,0):= Letter;
StrCopy(Greek, @Dict(Entries,1));
Entries:= Entries+1;            \(limit checks ignored for simplicity)
];

int I;
[Entries:= 0;
AddEntry(^A, "alpha");          \add items in arbitrary order
AddEntry(^D, "delta");
AddEntry(^B, "beta");
AddEntry(^C, "gamma");
BSort(Dict, Entries);           \sort entries by Greek name
for I:= 0 to Entries-1 do       \show sorted entries
    [ChOut(0, Dict(I,0));  ChOut(0, ^ );  Text(0, @Dict(I,1));  CrLf(0)];
]
Output:
A alpha
B beta
D delta
C gamma

zkl

The list of lists way is available or:

class P{var name,value;
   fcn init(nm,val){name,value=vm.arglist} 
   fcn __opLT(p){name<p.name}  // implementation of P1 < P2
}
// create list of pairs:
p:=List(P("sam","a"),P("fred","b"),P("chris","c"));
p.sort();
p.apply("name"); //-->L("chris","fred","sam")