Sort stability: Difference between revisions

m
syntax highlighting fixup automation
m (→‎{{header|Phix}}: inlined and therefore removed all the dopey "2nd sort depends on 1st" nonsense.)
m (syntax highlighting fixup automation)
Line 34:
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits}}
<syntaxhighlight lang="aarch64 assembly">
<lang AArch64 Assembly>
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program stableSort641.s */
Line 328:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
</lang>
<pre>
Name : London country : UK
Line 376:
The task description doesn't specify what form the "table" takes, but here it's assumed to be a tab-delimited text.
 
<langsyntaxhighlight lang="applescript">set aTable to "UK London
US New York
US Birmingham
Line 385:
set stableSortedOnColumn1 to (do shell script ("sort -st'" & tab & "' -k1,1 <<<" & quoted form of aTable))
return "Stable sorted on column 2:" & (linefeed & stableSortedOnColumn2) & (linefeed & linefeed & ¬
"Stable sorted on column 1:") & (linefeed & stableSortedOnColumn1)</langsyntaxhighlight>
 
{{output}}
<langsyntaxhighlight lang="applescript">"Stable sorted on column 2:
US Birmingham
UK Birmingham
Line 399:
US New York
US Birmingham"
</syntaxhighlight>
</lang>
 
=={{header|AutoHotkey}}==
Autohotkey has got a build-in sorting method for tables, which is stable.
<langsyntaxhighlight AutoHotkeylang="autohotkey">Table =
(
UK, London
Line 442:
ButtonSortCities:
LV_ModifyCol(3, "Sort")
Return</langsyntaxhighlight>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f SORT_STABILITY.AWK [-v width=x] -v field=x SORT_STABILITY.TXT
#
Line 473:
exit(0)
}
</syntaxhighlight>
</lang>
<p>input:</p>
<pre>
Line 550:
These functions use merge sort algorithm.
The sorting algorithm will be stable as long as the given function returns true for values considered equal:
<langsyntaxhighlight lang="elixir">cities = [ {"UK", "London"},
{"US", "New York"},
{"US", "Birmingham"},
Line 558:
IO.inspect Enum.sort(cities, fn a,b -> elem(a,0) >= elem(b,0) end)
IO.inspect Enum.sort_by(cities, fn {country, _city} -> country end)
IO.inspect Enum.sort_by(cities, fn {_country, city} -> city end)</langsyntaxhighlight>
{{out}}
<pre>
Line 568:
 
'''Note:''' If the function does not return true, the sorting is not stable and the order of equal terms may be shuffled:
<langsyntaxhighlight lang="elixir">IO.inspect Enum.sort(cities, fn a,b -> elem(a,0) > elem(b,0) end)</langsyntaxhighlight>
{{out}}
<pre>
Line 591:
 
=={{header|GAP}}==
<langsyntaxhighlight lang="gap"># According to section 21.18 of the reference manual, Sort is not stable (it's a Shell sort).
# However, SortingPerm is stable. We will see it on an example, showing indexes of elements after the sort.
 
Line 607:
PrintArray(TransposedMat(List([1 .. n], i -> [a[i], b[i]])));
# [ [ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B' ],
# [ 1, 2, 4, 8, 11, 13, 14, 16, 19, 3, 5, 6, 7, 9, 10, 12, 15, 17, 18, 20 ] ]</langsyntaxhighlight>
 
=={{header|Go}}==
Line 618:
{{trans|Java}}
{{works with|Groovy|1.8.1}}
<langsyntaxhighlight lang="groovy">def cityList = ['UK London', 'US New York', 'US Birmingham', 'UK Birmingham',].asImmutable()
[
'Sort by city': { city -> city[4..-1] },
Line 627:
println "\nAfter ${label}"
cityList.sort(false, orderBy).each{ println it }
}</langsyntaxhighlight>
 
Output:
Line 672:
 
The following sample demonstrates Java's sort stability:
<langsyntaxhighlight Javalang="java">import java.util.Arrays;
import java.util.Comparator;
 
Line 718:
System.out.println();
}
}</langsyntaxhighlight>
;Output
<pre>
Line 751:
At the time of writing this is already implemented in in Node.js and in the JS interpreters of all major browsers, including Microsoft Edge, but not according to the Mozilla implementations table, the older Internet Explorer. In earlier interpreters, sort stability depends on particular implementations.
 
<langsyntaxhighlight lang="javascript">ary = [["UK", "London"], ["US", "New York"], ["US", "Birmingham"], ["UK", "Birmingham"]]
print(ary);
 
Line 757:
print(ary);
 
/* a stable sort will output ["US", "Birmingham"] before ["UK", "Birmingham"] */</langsyntaxhighlight>
 
Stable implementations:
Line 777:
As of January 18, 2016 (Commit SHA 7835a72), the builtin sorting filters (notably sort/0 and sort_by/1) are stable; prior to that, stability was platform-dependent. This means that stability is NOT guaranteed in jq 1.5 or earlier. In the following, a version of jq with sorting stability has been used.
 
<langsyntaxhighlight lang="jq">[["UK", "London"],
["US", "New York"],
["US", "Birmingham"],
["UK", "Birmingham"]]
| sort_by(.[1])</langsyntaxhighlight>
 
Invocation:
Line 803:
=={{header|Kotlin}}==
The collections in Kotlin's standard library are thin wrappers around the corresponding JDK collections and, since the latter's sort methods are stable, so too are Kotlin's standard sort functions.
<langsyntaxhighlight lang="scala">// version 1.1.51
 
fun main(args: Array<String>) {
Line 812:
// sort by city
println("By city : ${cities.sortedBy { it.drop(3) } }")
}</langsyntaxhighlight>
 
{{out}}
Line 824:
Arrays can be sorted in two “built in" ways in Lasso:
 
<langsyntaxhighlight Lassolang="lasso">//Single param array:
array->sort
 
Line 831:
 
//The array can also be ordered by multiple values:
with i in array order by #i->second, #i->first do => { … } </langsyntaxhighlight>
 
Sorting of arrays by either method uses “Qucksort” and is therefore unstable. A simulation of increasing sort stability would be introduced with additional params such as the example of ordering by the second then the first pair values in the example above - but would not be guaranteed stable.
Line 838:
 
Sort by second value only:
<langsyntaxhighlight Lassolang="lasso">local(a = array('UK'='London','US'='New York','US'='Birmingham','UK'='Birmingham'))
with i in #a order by #i->second do => {^ #i->first+' - '+#i->second+'\r' ^}</langsyntaxhighlight>
{{out}}
<pre>US - Birmingham
Line 847:
 
Sort by second then by first:
<langsyntaxhighlight Lassolang="lasso">local(a = array('UK'='London','US'='New York','US'='Birmingham','UK'='Birmingham'))
with i in #a order by #i->second, #i->first do => {^ #i->first+' - '+#i->second+'\r' ^}</langsyntaxhighlight>
{{out}}
<pre>UK - Birmingham
Line 861:
 
Here's an example showing that SORT indeed unstable.
<syntaxhighlight lang="lb">
<lang lb>
randomize 0.5
N=15
Line 890:
end if
next
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 937:
 
Here is the stable sort
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Stable {
Inventory queue alfa
Line 965:
US Birmingham
 
</syntaxhighlight>
</lang>
 
 
Line 971:
We can sort in on key only. Lets make keys with two fields (based on fields lengths, except for last one)
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Stable1 {
Inventory queue alfa
Line 999:
US New York
 
</syntaxhighlight>
</lang>
 
Now second column is sorting (but it is one column all, no two columns). So lets see the unstable sort. Because all keys now are unique we just remove queue from Inventory definition.
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Stable2 {
Inventory alfa
Line 1,030:
US New York
 
</syntaxhighlight>
</lang>
 
So now we see that using unique keys in either type of inventories we get same output.
Line 1,042:
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Sort is not always stable. Ordering, which gives a list of indices such as to put the elements of the list in order, is stable. An example would be to sort the list (of lists) {{1, 2, 3}, {4, 5, 6}, {5, 4, 3}, {9, 5, 1}}, and doing so by looking at the 2nd value of each list:
<langsyntaxhighlight Mathematicalang="mathematica">mylist = {{1, 2, 3}, {4, 5, 6}, {5, 4, 3}, {9, 5, 1}};
Sort[mylist, (#1[[2]] < #2[[2]]) &]
#[[Ordering[#[[All, 2]]]]] &[mylist]</langsyntaxhighlight>
gives:
<langsyntaxhighlight Mathematicalang="mathematica">{{1, 2, 3}, {5, 4, 3}, {9, 5, 1}, {4, 5, 6}}
{{1, 2, 3}, {5, 4, 3}, {4, 5, 6}, {9, 5, 1}}</langsyntaxhighlight>
Showing that Sort is unstable, and that by using input[[Ordering[input]]] Ordering provides a way to make a stable sort.
 
Line 1,056:
Java's [http://java.sun.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List) Collections.sort()] and [http://java.sun.com/javase/6/docs/api/java/util/Arrays.html#sort(java.lang.Object%5B%5D) Arrays.sort()] methods are guaranteed stable. The following sample takes advantage of this to demonstrate sort stability.
 
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref savelog symbols nobinary
 
Line 1,111:
method compare(lft = Object, rgt = Object) public binary returns int
return (String lft).substring(0, 2).compareTo((String rgt).substring(0, 2))
</syntaxhighlight>
</lang>
;Output
<pre>
Line 1,141:
=={{header|Nim}}==
Default Nim sort in the algorithm module is stable.
<langsyntaxhighlight Nimlang="nim">import algorithm
 
const Records = [(country: "UK", city: "London"),
Line 1,160:
echo "Sorted by country name:"
for record in Records.sortedByIt(it.country):
echo record.country, " ", record.city</langsyntaxhighlight>
 
{{out}}
Line 1,186:
=={{header|ooRexx}}==
Open Object Rexx provides sort methods (<code>sort</code> and <code>sortWith(comparator)</code>) for its collection classes. By default these sort methods are implemented via an unstable <em>Quicksort</em> algorithm but the language does provide stable sorting methods (<code>stableSort</code> and <code>stableSortWith(comparator)</code>) implemented via a stable <em>Mergesort</em> algorithm.
<langsyntaxhighlight ooRexxlang="oorexx">/* Rexx */
Do
cities = .array~of('UK London', 'US New York', 'US Birmingham', 'UK Birmingham',)
Line 1,229:
End
Exit
</syntaxhighlight>
</lang>
;Output
<pre>
Line 1,270:
=={{header|OpenEdge/Progress}}==
The results can be forced to stable by ''additionally'' sorting on the ROWID of the record. If you leave the additional sort out, the indexes on the temp-table can influence the result.
<langsyntaxhighlight lang="progress">DEFINE TEMP-TABLE tt
FIELD country AS CHAR FORMAT 'x(2)'
FIELD city AS CHAR FORMAT 'x(16)'
Line 1,294:
MESSAGE
cc[1] SKIP(1) cc[2]
VIEW-AS ALERT-BOX.</langsyntaxhighlight>
 
'''Output:'''
Line 1,324:
 
Example:
<langsyntaxhighlight lang="oz">declare
Cities = ['UK'#'London'
'US'#'New York'
Line 1,334:
 
%% sort by country; NOT stable because '<' is not reflexiv
{Show {Sort Cities fun {$ A B} A.1 < B.1 end}}</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
Line 1,344:
=={{header|Perl}}==
The stability of Perl's in-built [http://perldoc.perl.org/functions/sort.html sort] function is version-dependent. If you want to guarantee a stable sort from it, you should use the following [http://perldoc.perl.org/sort.html sort pragma]:
<syntaxhighlight lang ="perl">use sort 'stable';</langsyntaxhighlight>
 
=={{header|Phix}}==
The standard sort method is merge sort, which is apparently stable, though I would be reluctant to guarantee that, or rely on it, especially given that a simple tag sort is irrefutably stable since it explicitly orders by tag (aka original position) within any equal keys.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">test</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"UK"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"London"</span><span style="color: #0000FF;">},</span>
Line 1,373:
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tags</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">custom_sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tag_cmp</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)))</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">extract</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tags</span><span style="color: #0000FF;">),{</span><span style="color: #004600;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
<!--</langsyntaxhighlight>-->
{{Out}}
<pre>
Line 1,408:
R uses shell sort (stable) or quick sort (unstable). An easy way to show the difference is names to vector entries, then check if names are still ordered after sorting.
 
<syntaxhighlight lang="r">
<lang R>
# First, define a bernoulli sample, of length 26.
x <- sample(c(0, 1), 26, replace=T)
Line 1,431:
# e h j n q s u x z a b c d f g i k l m o p r t v w y
# 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
Line 1,437:
Racket comes with a standard <tt>sort</tt> function, which is documented [[http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._sort%29%29 here]]. It is documented as stable.
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 1,455:
;; -> '(("US" "Birmingham") ("UK" "Birmingham")
;; ("UK" "London") ("US" "New York"))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 1,463:
 
Short demonstration for sorting only on the second item of each array:
<syntaxhighlight lang="raku" perl6line>use v6;
my @cities =
['UK', 'London'],
Line 1,471:
;
 
.say for @cities.sort: { .[1] };</langsyntaxhighlight>
 
=={{header|REBOL}}==
<langsyntaxhighlight lang="rebol">; REBOL's sort function is not stable by default. You need to use a custom comparator to make it so.
 
blk: [
Line 1,491:
UK Birmingham
]
sort/skip/compare blk 2 func [a b] [either a < b [-1] [either a > b [1] [0]]]</langsyntaxhighlight>
 
=={{header|REXX}}==
Classic REXX has no built-in routines for sorting, so this programming example uses a classic ''bubble sort'' &nbsp; (which is stable).
<langsyntaxhighlight lang="rexx">/*REXX program sorts a (stemmed) array using a (stable) bubble─sort algorithm. */
call gen@ /*generate the array elements (strings)*/
call show 'before sort' /*show the before array elements. */
Line 1,517:
end /*#*/; #= # - 1; return /*adjust for the DO loop index; return*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: do j=1 for #; say ' element' right(j,length(#)) arg(1)":" @.j; end; return</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default list:}}
<pre>
Line 1,532:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
aList = [["UK", "London"],
["US", "New York"],
Line 1,538:
["UK", "Birmingham"]]
see sort(aList,2)
</syntaxhighlight>
</lang>
 
=={{header|Ruby}}==
Line 1,544:
 
{{works with|MRI|1.8.7, 1.9.2}}
<langsyntaxhighlight lang="ruby">ary = [["UK", "London"],
["US", "New York"],
["US", "Birmingham"],
Line 1,550:
p ary.sort {|a,b| a[1] <=> b[1]}
# MRI reverses the Birminghams:
# => [["UK", "Birmingham"], ["US", "Birmingham"], ["UK", "London"], ["US", "New York"]]</langsyntaxhighlight>
 
Other implementations of Ruby might differ. Old versions of [[JRuby]] used java.util.Arrays.sort, which was a stable sort, but was slower than MRI. To increase performance, JRuby switched to quicksort, which is not stable. [http://jira.codehaus.org/browse/JRUBY-2198 (3)]
Line 1,557:
To code a stable sort, without implementing another sorting algorithm (such as [[Sorting algorithms/Merge sort|merge sort]]), use a Schwartzian transform.
 
<langsyntaxhighlight lang="ruby">class Array
def stable_sort
n = -1
Line 1,576:
sort_by {|x| n += 1; [(yield x), n]}
end
end</langsyntaxhighlight>
 
<langsyntaxhighlight lang="ruby">ary = [["UK", "London"],
["US", "New York"],
["US", "Birmingham"],
Line 1,585:
# => [["US", "Birmingham"], ["UK", "Birmingham"], ["UK", "London"], ["US", "New York"]]
p ary.stable_sort_by {|x| x[1]}
# => [["US", "Birmingham"], ["UK", "Birmingham"], ["UK", "London"], ["US", "New York"]]</langsyntaxhighlight>
 
=={{header|Rust}}==
Rust's builtin sorts (.sort(), .sort_by(...), .sort_by_key(...)) are all stable
 
<langsyntaxhighlight lang="rust">fn main() {
let country_city = [
("UK", "London"),
Line 1,618:
println!("{} {}", x.0, x.1);
}
}</langsyntaxhighlight>
 
Output: <pre>Original:
Line 1,646:
 
Examples:
<langsyntaxhighlight lang="scala">scala> val list = List((1, 'c'), (1, 'b'), (2, 'a'))
list: List[(Int, Char)] = List((1,c), (1,b), (2,a))
 
Line 1,664:
 
scala> cities.sortBy(_ substring 4)
res47: Seq[String] = ArrayBuffer(US Birmingham, UK Birmingham, UK London, US New York)</langsyntaxhighlight>
Besides that, there is the object <tt>scala.util.Sorting</tt>, which provides <tt>quickSort<tt> and <tt>stableSort</tt>. The former is only provided on <tt>Array</tt>, but the latter is provided over both <tt>Array</tt> and <tt>Seq</tt>. These sorts operate in-place, with the one over <tt>Seq</tt> returning a sorted <tt>Array</tt>. Here is one example:
<langsyntaxhighlight lang="scala">scala> val cityArray = cities.toArray
cityArray: Array[String] = Array(UK London, US New York, US Birmingham, UK Birmingham)
 
Line 1,672:
 
scala> cityArray
res56: Array[String] = Array(US Birmingham, UK Birmingham, UK London, US New York)</langsyntaxhighlight>
 
=={{header|Sidef}}==
Sidef uses the stable merge-sort algorithm for sorting an array.
<langsyntaxhighlight lang="ruby">var table = [
<UK London>,
<US New\ York>,
Line 1,685:
table.sort {|a,b| a[0] <=> b[0]}.each { |col|
say "#{col[0]} #{col[1]}"
}</langsyntaxhighlight>
{{out}}
<pre>UK London
Line 1,709:
 
Below we illustrate the points made in the task description using the stable insertion sort.
<langsyntaxhighlight lang="ecmascript">import "/sort" for Cmp, Sort
 
var data = [ ["UK", "London"], ["US", "New York"], ["US", "Birmingham"], ["UK", "Birmingham"] ]
Line 1,730:
var data3 = data.toList
Sort.insertion(data3, cmp2)
System.print(" " + data3.join("\n "))</langsyntaxhighlight>
 
{{out}}
Line 1,755:
=={{header|zkl}}==
zkl's sort methods don't mention stability or columns, they are comparison based.
<langsyntaxhighlight lang="zkl">fcn sortByColumn(list,col)
{ list.sort('wrap(city1,city2){ city1[col]<city2[col] }) }</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">cities:=List(
T("UK", "London"), T("US", "New York"),
T("US", "Birmingham"),T("UK", "Birmingham"), );
sortByColumn(cities,0).concat("\n").println("\n------");
sortByColumn(cities,1).concat("\n").println();</langsyntaxhighlight>
{{out}}
<pre>
10,333

edits