Sorting
Sort an array in place or into a copy, in either order, row by row, or on several cores.
Sort in place
sort puts the elements of an array in ascending order. It changes the array itself and returns nothing (JavaScript
returns the same array). No extra copy of your data is made.
import numpy as np
import kwker
temperatures = np.array([21.5, 18.0, 25.25, 19.75, 23.0])
kwker.sort(temperatures)
print(temperatures)
[18. 19.75 21.5 23. 25.25]
fn main() {
let mut temperatures = [21.5, 18.0, 25.25, 19.75, 23.0];
kwker::sort(&mut temperatures);
println!("{temperatures:?}");
}
[18.0, 19.75, 21.5, 23.0, 25.25]
#include <stdio.h>
#include <kwker.h>
int main(void) {
double temperatures[] = {21.5, 18.0, 25.25, 19.75, 23.0};
kwker_f64_sort(temperatures, 5);
for (int i = 0; i < 5; i++) printf(i ? " %g" : "%g", temperatures[i]);
printf("\n");
return 0;
}
18 19.75 21.5 23 25.25
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
std::vector<double> temperatures{21.5, 18.0, 25.25, 19.75, 23.0};
kwker::sort(temperatures);
for (double t : temperatures) std::cout << t << ' ';
std::cout << '\n';
}
18 19.75 21.5 23 25.25
const kwk = require("kwker");
const temperatures = new Float64Array([21.5, 18.0, 25.25, 19.75, 23.0]);
kwk.sort(temperatures);
console.log(temperatures);
Float64Array(5) [ 18, 19.75, 21.5, 23, 25.25 ]
package main
import (
"fmt"
"kwker.io/go/kwker"
)
func main() {
temperatures := []float64{21.5, 18.0, 25.25, 19.75, 23.0}
kwker.Sort(temperatures)
fmt.Println(temperatures)
}
[18 19.75 21.5 23 25.25]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
double[] temperatures = {21.5, 18.0, 25.25, 19.75, 23.0};
Kwker.sort(temperatures);
System.out.println(Arrays.toString(temperatures));
}
}
[18.0, 19.75, 21.5, 23.0, 25.25]
using Kwker;
var temperatures = new double[] { 21.5, 18.0, 25.25, 19.75, 23.0 };
Sorter.Sort(temperatures);
Console.WriteLine(string.Join(" ", temperatures));
18 19.75 21.5 23 25.25
Get a sorted copy
To keep the original, sort a copy. In Python, kwker.sorted(a) returns a new sorted array and leaves a
unchanged; it always returns a flat (1-D) array.
import numpy as np
import kwker
ids = np.array([42, 7, 1000, 7, 3], dtype=np.uint32)
print(kwker.sorted(ids))
print(ids)
[ 3 7 7 42 1000]
[ 42 7 1000 7 3]
fn main() {
let ids: [u32; 5] = [42, 7, 1000, 7, 3];
let mut sorted = ids.to_vec();
kwker::sort(&mut sorted);
println!("{sorted:?}");
println!("{ids:?}");
}
[3, 7, 7, 42, 1000] [42, 7, 1000, 7, 3]
#include <stdio.h>
#include <string.h>
#include <kwker.h>
int main(void) {
const uint32_t ids[] = {42, 7, 1000, 7, 3};
uint32_t sorted[5];
memcpy(sorted, ids, sizeof ids);
kwker_u32_sort(sorted, 5);
for (int i = 0; i < 5; i++) printf(i ? " %u" : "%u", sorted[i]);
printf("\n");
for (int i = 0; i < 5; i++) printf(i ? " %u" : "%u", ids[i]);
printf("\n");
return 0;
}
3 7 7 42 1000 42 7 1000 7 3
#include <cstdint>
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
const std::vector<uint32_t> ids{42, 7, 1000, 7, 3};
std::vector<uint32_t> sorted = ids;
kwker::sort(sorted);
for (auto x : sorted) std::cout << x << ' ';
std::cout << '\n';
for (auto x : ids) std::cout << x << ' ';
std::cout << '\n';
}
3 7 7 42 1000 42 7 1000 7 3
const kwk = require("kwker");
const ids = new Uint32Array([42, 7, 1000, 7, 3]);
const sorted = kwk.sort(ids.slice());
console.log(sorted);
console.log(ids);
Uint32Array(5) [ 3, 7, 7, 42, 1000 ]
Uint32Array(5) [ 42, 7, 1000, 7, 3 ]
package main
import (
"fmt"
"slices"
"kwker.io/go/kwker"
)
func main() {
ids := []uint32{42, 7, 1000, 7, 3}
sorted := slices.Clone(ids)
kwker.Sort(sorted)
fmt.Println(sorted)
fmt.Println(ids)
}
[3 7 7 42 1000] [42 7 1000 7 3]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] ids = {42, 7, 1000, 7, 3};
int[] sorted = ids.clone();
Kwker.sort(sorted);
System.out.println(Arrays.toString(sorted));
System.out.println(Arrays.toString(ids));
}
}
[3, 7, 7, 42, 1000] [42, 7, 1000, 7, 3]
using Kwker;
var ids = new uint[] { 42, 7, 1000, 7, 3 };
var sorted = (uint[])ids.Clone();
Sorter.Sort(sorted);
Console.WriteLine(string.Join(" ", sorted));
Console.WriteLine(string.Join(" ", ids));
3 7 7 42 1000 42 7 1000 7 3
Largest first
Every call takes a descending order to reverse the result: descending=True in Python, sort_descending or
Order::DESCENDING in Rust, KWKER_DESCENDING in C, Order::descending in C++ and { descending: true } in
JavaScript.
import numpy as np
import kwker
scores = np.array([72, 95, 88, 61, 95])
kwker.sort(scores, descending=True)
print(scores)
[95 95 88 72 61]
fn main() {
let mut scores = [72, 95, 88, 61, 95];
kwker::sort_descending(&mut scores);
println!("{scores:?}");
}
[95, 95, 88, 72, 61]
#include <stdio.h>
#include <kwker.h>
int main(void) {
int32_t scores[] = {72, 95, 88, 61, 95};
kwker_i32_sort_order(scores, 5, KWKER_DESCENDING);
for (int i = 0; i < 5; i++) printf(i ? " %d" : "%d", scores[i]);
printf("\n");
return 0;
}
95 95 88 72 61
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
std::vector<int> scores{72, 95, 88, 61, 95};
kwker::sort(scores, kwker::Order::descending);
for (int s : scores) std::cout << s << ' ';
std::cout << '\n';
}
95 95 88 72 61
const kwk = require("kwker");
const scores = new Int32Array([72, 95, 88, 61, 95]);
kwk.sort(scores, { descending: true });
console.log(scores);
Int32Array(5) [ 95, 95, 88, 72, 61 ]
package main
import (
"fmt"
"kwker.io/go/kwker"
)
func main() {
scores := []int32{72, 95, 88, 61, 95}
kwker.SortOrder(scores, kwker.Descending)
fmt.Println(scores)
}
[95 95 88 72 61]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] scores = {72, 95, 88, 61, 95};
Kwker.sort(scores, Kwker.DESCENDING);
System.out.println(Arrays.toString(scores));
}
}
[95, 95, 88, 72, 61]
using Kwker;
var scores = new int[] { 72, 95, 88, 61, 95 };
Sorter.Sort(scores, Order.Descending);
Console.WriteLine(string.Join(" ", scores));
95 95 88 72 61
Sort each row
Sorting each row of a matrix on its own is one call: axis=1 in Python (axis=0 sorts every column; without axis,
all elements are sorted as one flat list), and sort_rows in Rust, C and C++ for a row-major matrix stored as one
array. In JavaScript, sort each row's view.
import numpy as np
import kwker
m = np.array([[3, 1, 2],
[9, 7, 8]])
kwker.sort(m, axis=1)
print(m)
[[1 2 3]
[7 8 9]]
use kwker::Order;
fn main() {
// 2 rows of 3, stored row after row
let mut m = [3, 1, 2,
9, 7, 8];
kwker::sort_rows(&mut m, 3, Order::ASCENDING);
for row in m.chunks(3) {
println!("{row:?}");
}
}
[1, 2, 3] [7, 8, 9]
#include <stdio.h>
#include <kwker.h>
int main(void) {
int32_t m[2][3] = {{3, 1, 2},
{9, 7, 8}};
kwker_i32_sort_rows(&m[0][0], 2, 3, KWKER_ASCENDING);
for (int r = 0; r < 2; r++) printf("%d %d %d\n", m[r][0], m[r][1], m[r][2]);
return 0;
}
1 2 3 7 8 9
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
// 2 rows of 3, stored row after row
std::vector<int> m{3, 1, 2,
9, 7, 8};
kwker::sort_rows(m, 3);
for (size_t r = 0; r < 2; r++) std::cout << m[3 * r] << ' ' << m[3 * r + 1] << ' ' << m[3 * r + 2] << '\n';
}
1 2 3 7 8 9
const kwk = require("kwker");
// 2 rows of 3, stored row after row
const m = new Int32Array([3, 1, 2,
9, 7, 8]);
for (let r = 0; r < 2; r++) kwk.sort(m.subarray(3 * r, 3 * r + 3));
console.log(m);
Int32Array(6) [ 1, 2, 3, 7, 8, 9 ]
package main
import (
"fmt"
"kwker.io/go/kwker"
)
func main() {
// two rows of three
m := []int32{3, 1, 2, 9, 7, 8}
kwker.SortRows(m, 3, kwker.Ascending)
fmt.Println(m[:3])
fmt.Println(m[3:])
}
[1 2 3] [7 8 9]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
// two rows of three
int[] m = {3, 1, 2, 9, 7, 8};
Kwker.sortRows(m, 3, Kwker.ASCENDING);
System.out.println(Arrays.toString(Arrays.copyOfRange(m, 0, 3)));
System.out.println(Arrays.toString(Arrays.copyOfRange(m, 3, 6)));
}
}
[1, 2, 3] [7, 8, 9]
using Kwker;
// two rows of three
var m = new int[] { 3, 1, 2, 9, 7, 8 };
Sorter.SortRows(m, 3);
Console.WriteLine(string.Join(" ", m[..3]));
Console.WriteLine(string.Join(" ", m[3..]));
1 2 3 7 8 9
Big arrays: use more cores
For millions of elements, sort on several cores: threads= in Python, sort_mt in Rust, C and C++, SortMT in Go and
C#, sortMt in Java. 0 threads means the default for your machine. The result is the same as with one thread. (The
WebAssembly build runs on one thread.)
import numpy as np
import kwker
a = np.random.default_rng(1).random(5_000_000)
b = a.copy()
kwker.sort(a)
kwker.sort(b, threads=4)
print(np.array_equal(a, b))
True
use kwker::Order;
fn main() {
// 5 million pseudo-random numbers in [0, 1)
let mut x = 1u64;
let a: Vec<f64> = (0..5_000_000)
.map(|_| {
x = x.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
(x >> 11) as f64 / (1u64 << 53) as f64
})
.collect();
let mut one = a.clone();
let mut four = a;
kwker::sort(&mut one);
kwker::sort_mt(&mut four, Order::ASCENDING, 4);
println!("{}", one == four);
}
true
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <kwker.h>
int main(void) {
size_t n = 5000000;
double* one = malloc(n * sizeof(double));
double* four = malloc(n * sizeof(double));
uint64_t x = 1;
for (size_t i = 0; i < n; i++) {
x = x * 6364136223846793005u + 1442695040888963407u;
one[i] = (double)(x >> 11) / 9007199254740992.0;
}
memcpy(four, one, n * sizeof(double));
kwker_f64_sort(one, n);
kwker_f64_sort_mt(four, n, KWKER_ASCENDING, 4);
printf("%s\n", memcmp(one, four, n * sizeof(double)) == 0 ? "true" : "false");
free(one);
free(four);
return 0;
}
true
#include <cstdint>
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
std::vector<double> one(5000000);
uint64_t x = 1;
for (double& v : one) {
x = x * 6364136223846793005u + 1442695040888963407u;
v = double(x >> 11) / 9007199254740992.0;
}
std::vector<double> four = one;
kwker::sort(one);
kwker::sort_mt(four, 4);
std::cout << std::boolalpha << (one == four) << '\n';
}
true
package main
import (
"fmt"
"slices"
"kwker.io/go/kwker"
)
func main() {
// 5 million pseudo-random numbers in [0, 1)
one := make([]float64, 5_000_000)
x := uint64(1)
for i := range one {
x = x*6364136223846793005 + 1442695040888963407
one[i] = float64(x>>11) / (1 << 53)
}
four := slices.Clone(one)
kwker.Sort(one)
kwker.SortMT(four, kwker.Ascending, 4)
fmt.Println(slices.Equal(one, four))
}
true
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
double[] one = new double[5_000_000];
long x = 1;
for (int i = 0; i < one.length; i++) {
x = x * 6364136223846793005L + 1442695040888963407L;
one[i] = (double) (x >>> 11) / 9007199254740992.0;
}
double[] four = one.clone();
Kwker.sort(one);
Kwker.sortMt(four, Kwker.ASCENDING, 4);
System.out.println(Arrays.equals(one, four));
}
}
true
using Kwker;
var one = new double[5_000_000];
ulong x = 1;
for (int i = 0; i < one.Length; i++)
{
x = unchecked(x * 6364136223846793005UL + 1442695040888963407UL);
one[i] = (x >> 11) / 9007199254740992.0;
}
var four = (double[])one.Clone();
Sorter.Sort(one);
Sorter.SortMT(four, Order.Ascending, 4);
Console.WriteLine(one.AsSpan().SequenceEqual(four));
True
Every number type
Kwker sorts signed and unsigned integers of 8, 16, 32 and 64 bits, and 32- and 64-bit floats, each in its own format. Half-precision and 8-bit float formats (float16, bfloat16, FP8) and 128-bit
integers are available in the native packages.
import numpy as np
import kwker
print(kwker.sorted(np.array([5, -128, 127, 0], dtype=np.int8)))
print(kwker.sorted(np.array([65535, 1, 300], dtype=np.uint16)))
print(kwker.sorted(np.array([2**63 - 1, -(2**63), 0], dtype=np.int64)))
print(kwker.sorted(np.array([2.5, -1.25, 0.0], dtype=np.float32)))
[-128 0 5 127]
[ 1 300 65535]
[-9223372036854775808 0 9223372036854775807]
[-1.25 0. 2.5 ]
fn main() {
let mut a: [i8; 4] = [5, -128, 127, 0];
let mut b: [u16; 3] = [65535, 1, 300];
let mut c: [i64; 3] = [i64::MAX, i64::MIN, 0];
let mut d: [f32; 3] = [2.5, -1.25, 0.0];
kwker::sort(&mut a);
kwker::sort(&mut b);
kwker::sort(&mut c);
kwker::sort(&mut d);
println!("{a:?}\n{b:?}\n{c:?}\n{d:?}");
}
[-128, 0, 5, 127] [1, 300, 65535] [-9223372036854775808, 0, 9223372036854775807] [-1.25, 0.0, 2.5]
#include <inttypes.h>
#include <stdio.h>
#include <kwker.h>
int main(void) {
int8_t a[] = {5, -128, 127, 0};
uint16_t b[] = {65535, 1, 300};
int64_t c[] = {INT64_MAX, INT64_MIN, 0};
float d[] = {2.5f, -1.25f, 0.0f};
kwker_i8_sort(a, 4);
kwker_u16_sort(b, 3);
kwker_i64_sort(c, 3);
kwker_f32_sort(d, 3);
printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]);
printf("%u %u %u\n", b[0], b[1], b[2]);
printf("%" PRId64 " %" PRId64 " %" PRId64 "\n", c[0], c[1], c[2]);
printf("%g %g %g\n", d[0], d[1], d[2]);
return 0;
}
-128 0 5 127 1 300 65535 -9223372036854775808 0 9223372036854775807 -1.25 0 2.5
#include <cstdint>
#include <iostream>
#include <limits>
#include <vector>
#include <kwker.hpp>
template <class T> void print(const std::vector<T>& v) {
for (T x : v) std::cout << +x << ' '; // (+ prints 8-bit integers as numbers)
std::cout << '\n';
}
int main() {
std::vector<int8_t> a{5, -128, 127, 0};
std::vector<uint16_t> b{65535, 1, 300};
std::vector<int64_t> c{std::numeric_limits<int64_t>::max(), std::numeric_limits<int64_t>::min(), 0};
std::vector<float> d{2.5f, -1.25f, 0.0f};
kwker::sort(a);
kwker::sort(b);
kwker::sort(c);
kwker::sort(d);
print(a);
print(b);
print(c);
print(d);
}
-128 0 5 127 1 300 65535 -9223372036854775808 0 9223372036854775807 -1.25 0 2.5
const kwk = require("kwker");
console.log(kwk.sort(new Int8Array([5, -128, 127, 0])));
console.log(kwk.sort(new Uint16Array([65535, 1, 300])));
console.log(kwk.sort(new BigInt64Array([2n ** 63n - 1n, -(2n ** 63n), 0n])));
console.log(kwk.sort(new Float32Array([2.5, -1.25, 0.0])));
Int8Array(4) [ -128, 0, 5, 127 ]
Uint16Array(3) [ 1, 300, 65535 ]
BigInt64Array(3) [ -9223372036854775808n, 0n, 9223372036854775807n ]
Float32Array(3) [ -1.25, 0, 2.5 ]
package main
import (
"fmt"
"math"
"kwker.io/go/kwker"
)
func main() {
a := []int8{5, -128, 127, 0}
b := []uint16{65535, 1, 300}
c := []int64{math.MaxInt64, math.MinInt64, 0}
d := []float32{2.5, -1.25, 0.0}
kwker.Sort(a)
kwker.Sort(b)
kwker.Sort(c)
kwker.Sort(d)
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(d)
}
[-128 0 5 127] [1 300 65535] [-9223372036854775808 0 9223372036854775807] [-1.25 0 2.5]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
byte[] a = {5, -128, 127, 0};
char[] b = {65535, 1, 300}; // char: unsigned 16-bit numbers
long[] c = {Long.MAX_VALUE, Long.MIN_VALUE, 0};
float[] d = {2.5f, -1.25f, 0.0f};
Kwker.sort(a);
Kwker.sort(b);
Kwker.sort(c);
Kwker.sort(d);
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(new String(b).chars().toArray()));
System.out.println(Arrays.toString(c));
System.out.println(Arrays.toString(d));
}
}
[-128, 0, 5, 127] [1, 300, 65535] [-9223372036854775808, 0, 9223372036854775807] [-1.25, 0.0, 2.5]
using Kwker;
var a = new sbyte[] { 5, -128, 127, 0 };
var b = new ushort[] { 65535, 1, 300 };
var c = new long[] { long.MaxValue, long.MinValue, 0 };
var d = new float[] { 2.5f, -1.25f, 0.0f };
Sorter.Sort(a);
Sorter.Sort(b);
Sorter.Sort(c);
Sorter.Sort(d);
Console.WriteLine(string.Join(" ", a));
Console.WriteLine(string.Join(" ", b));
Console.WriteLine(string.Join(" ", c));
Console.WriteLine(string.Join(" ", d));
-128 0 5 127 1 300 65535 -9223372036854775808 0 9223372036854775807 -1.25 0 2.5
Is the sort stable?
A sort is stable when equal elements keep their original order. For plain numbers this makes no difference: equal numbers are identical, so you cannot tell them apart.
Tip
When the order of equal keys matters, for example when you reorder other data by a key, use
argsort. It is always stable.
Missing values (NaN)
Kwker puts every NaN at the end, in both directions. Ask for NaNs first to put them at the start instead: nans_first=True in Python,
NanPlacement::First in Rust, KWKER_NANS_FIRST in C, Order::nans_first in C++ and { nansFirst: true } in
JavaScript.
import numpy as np
import kwker
readings = np.array([3.2, np.nan, 1.5, np.nan, 2.8])
print(kwker.sorted(readings))
print(kwker.sorted(readings, descending=True))
print(kwker.sorted(readings, nans_first=True))
[1.5 2.8 3.2 nan nan]
[3.2 2.8 1.5 nan nan]
[nan nan 1.5 2.8 3.2]
use kwker::{NanPlacement, Order};
fn main() {
let readings = [3.2, f64::NAN, 1.5, f64::NAN, 2.8];
let mut a = readings;
kwker::sort(&mut a);
println!("{a:?}");
let mut b = readings;
kwker::sort_descending(&mut b);
println!("{b:?}");
let mut c = readings;
kwker::sort_by_order(&mut c, Order { nans: NanPlacement::First, ..Order::ASCENDING });
println!("{c:?}");
}
[1.5, 2.8, 3.2, NaN, NaN] [3.2, 2.8, 1.5, NaN, NaN] [NaN, NaN, 1.5, 2.8, 3.2]
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <kwker.h>
static void print(const double* a, int n) {
for (int i = 0; i < n; i++) printf(i ? " %g" : "%g", a[i]);
printf("\n");
}
int main(void) {
const double readings[] = {3.2, NAN, 1.5, NAN, 2.8};
const uint32_t orders[] = {KWKER_ASCENDING, KWKER_DESCENDING, KWKER_NANS_FIRST};
for (int k = 0; k < 3; k++) {
double a[5];
memcpy(a, readings, sizeof readings);
kwker_f64_sort_order(a, 5, orders[k]);
print(a, 5);
}
return 0;
}
1.5 2.8 3.2 nan nan 3.2 2.8 1.5 nan nan nan nan 1.5 2.8 3.2
#include <cmath>
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
const std::vector<double> readings{3.2, NAN, 1.5, NAN, 2.8};
for (auto order : {kwker::Order::ascending, kwker::Order::descending, kwker::Order::nans_first}) {
std::vector<double> a = readings;
kwker::sort(a, order);
for (double x : a) std::cout << x << ' ';
std::cout << '\n';
}
}
1.5 2.8 3.2 nan nan 3.2 2.8 1.5 nan nan nan nan 1.5 2.8 3.2
const kwk = require("kwker");
const readings = new Float64Array([3.2, NaN, 1.5, NaN, 2.8]);
console.log(kwk.sort(readings.slice()));
console.log(kwk.sort(readings.slice(), { descending: true }));
console.log(kwk.sort(readings.slice(), { nansFirst: true }));
Float64Array(5) [ 1.5, 2.8, 3.2, NaN, NaN ]
Float64Array(5) [ 3.2, 2.8, 1.5, NaN, NaN ]
Float64Array(5) [ NaN, NaN, 1.5, 2.8, 3.2 ]
package main
import (
"fmt"
"math"
"slices"
"kwker.io/go/kwker"
)
func main() {
readings := []float64{3.2, math.NaN(), 1.5, math.NaN(), 2.8}
for _, order := range []kwker.Order{kwker.Ascending, kwker.Descending, kwker.NaNsFirst} {
x := slices.Clone(readings)
kwker.SortOrder(x, order)
fmt.Println(x)
}
}
[1.5 2.8 3.2 NaN NaN] [3.2 2.8 1.5 NaN NaN] [NaN NaN 1.5 2.8 3.2]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
double[] readings = {3.2, Double.NaN, 1.5, Double.NaN, 2.8};
for (int order : new int[] {Kwker.ASCENDING, Kwker.DESCENDING, Kwker.NANS_FIRST}) {
double[] x = readings.clone();
Kwker.sort(x, order);
System.out.println(Arrays.toString(x));
}
}
}
[1.5, 2.8, 3.2, NaN, NaN] [3.2, 2.8, 1.5, NaN, NaN] [NaN, NaN, 1.5, 2.8, 3.2]
using Kwker;
var readings = new double[] { 3.2, double.NaN, 1.5, double.NaN, 2.8 };
foreach (var order in new[] { Order.Ascending, Order.Descending, Order.NansFirst })
{
var x = (double[])readings.Clone();
Sorter.Sort(x, order);
Console.WriteLine(string.Join(" ", x));
}
1.5 2.8 3.2 NaN NaN 3.2 2.8 1.5 NaN NaN NaN NaN 1.5 2.8 3.2
Two more rules make float results the same everywhere:
-0.0comes before0.0. They compare equal in most languages, but Kwker keeps a fixed order between them.-infcomes first andinfcomes last among the numbers.
Related
- Top-k and selection: the largest or smallest values without sorting everything.
- Order and ranking: positions, ranks and multi-column sorts.
- Strings: text in byte, case-insensitive or natural order.
- API reference:
sort