Sorting keys with values
A key-value sort orders one array, the keys, and moves the matching entries of a second array, the values, along with them, in one call and without building an order array first.
Sort keys and values together
sort_kv(keys, values) sorts both arrays in place. values[i] stays with keys[i].
import numpy as np
import kwker
order_id = np.array([1042, 1007, 1093, 1001], dtype=np.uint32)
amount = np.array([25.0, 99.5, 12.75, 40.0])
kwker.sort_kv(order_id, amount)
print(order_id)
print(amount)
[1001 1007 1042 1093]
[40. 99.5 25. 12.75]
fn main() {
let mut order_id: [u32; 4] = [1042, 1007, 1093, 1001];
let mut amount = [25.0, 99.5, 12.75, 40.0];
kwker::sort_kv(&mut order_id, &mut amount);
println!("{order_id:?}");
println!("{amount:?}");
}
[1001, 1007, 1042, 1093] [40.0, 99.5, 25.0, 12.75]
#include <stdio.h>
#include <kwker.h>
int main(void) {
uint32_t order_id[] = {1042, 1007, 1093, 1001};
double amount[] = {25.0, 99.5, 12.75, 40.0};
kwker_u32_sort_kv(order_id, amount, sizeof(double), 4, KWKER_ASCENDING);
for (int i = 0; i < 4; i++) printf("%u %g\n", order_id[i], amount[i]);
return 0;
}
1001 40 1007 99.5 1042 25 1093 12.75
#include <cstdint>
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
std::vector<uint32_t> order_id{1042, 1007, 1093, 1001};
std::vector<double> amount{25.0, 99.5, 12.75, 40.0};
kwker::sort_kv(order_id.data(), amount.data(), order_id.size());
for (size_t i = 0; i < order_id.size(); i++) std::cout << order_id[i] << ' ' << amount[i] << '\n';
}
1001 40 1007 99.5 1042 25 1093 12.75
const kwk = require("kwker");
const orderId = new Uint32Array([1042, 1007, 1093, 1001]);
const amount = new Float64Array([25.0, 99.5, 12.75, 40.0]);
kwk.sortKV(orderId, amount);
console.log(orderId);
console.log(amount);
Uint32Array(4) [ 1001, 1007, 1042, 1093 ]
Float64Array(4) [ 40, 99.5, 25, 12.75 ]
package main
import (
"fmt"
"kwker.io/go/kwker"
)
func main() {
orderID := []uint32{1042, 1007, 1093, 1001}
amount := []float64{25.0, 99.5, 12.75, 40.0}
kwker.SortKV(orderID, amount, kwker.Ascending)
fmt.Println(orderID)
fmt.Println(amount)
}
[1001 1007 1042 1093] [40 99.5 25 12.75]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] orderId = {1042, 1007, 1093, 1001};
double[] amount = {25.0, 99.5, 12.75, 40.0};
Kwker.sortKV(orderId, amount, Kwker.ASCENDING);
System.out.println(Arrays.toString(orderId));
System.out.println(Arrays.toString(amount));
}
}
[1001, 1007, 1042, 1093] [40.0, 99.5, 25.0, 12.75]
using Kwker;
var orderId = new uint[] { 1042, 1007, 1093, 1001 };
var amount = new double[] { 25.0, 99.5, 12.75, 40.0 };
Sorter.SortKV(orderId, amount);
Console.WriteLine(string.Join(" ", orderId));
Console.WriteLine(string.Join(" ", amount));
1001 1007 1042 1093 40 99.5 25 12.75
Keep equal keys in order: the stable sort
By default, values with equal keys may end up in any order among themselves. That is the fastest choice. Ask for the
stable sort to keep them in their original order: stable=True in Python, sort_kv_stable in Rust, C and C++, and
{ stable: true } in JavaScript.
import numpy as np
import kwker
day = np.array([3, 1, 3, 2, 1], dtype=np.uint32)
event = np.array([30, 10, 31, 20, 11], dtype=np.int64)
kwker.sort_kv(day, event, stable=True)
print(day)
print(event)
[1 1 2 3 3]
[10 11 20 30 31]
fn main() {
let mut day: [u32; 5] = [3, 1, 3, 2, 1];
let mut event: [i64; 5] = [30, 10, 31, 20, 11];
kwker::sort_kv_stable(&mut day, &mut event);
println!("{day:?}");
println!("{event:?}");
}
[1, 1, 2, 3, 3] [10, 11, 20, 30, 31]
#include <inttypes.h>
#include <stdio.h>
#include <kwker.h>
int main(void) {
uint32_t day[] = {3, 1, 3, 2, 1};
int64_t event[] = {30, 10, 31, 20, 11};
kwker_u32_sort_kv_stable(day, event, sizeof(int64_t), 5, KWKER_ASCENDING);
for (int i = 0; i < 5; i++) printf("%u %" PRId64 "\n", day[i], event[i]);
return 0;
}
1 10 1 11 2 20 3 30 3 31
#include <cstdint>
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
std::vector<uint32_t> day{3, 1, 3, 2, 1};
std::vector<int64_t> event{30, 10, 31, 20, 11};
kwker::sort_kv_stable(day.data(), event.data(), day.size());
for (size_t i = 0; i < day.size(); i++) std::cout << day[i] << ' ' << event[i] << '\n';
}
1 10 1 11 2 20 3 30 3 31
const kwk = require("kwker");
const day = new Uint32Array([3, 1, 3, 2, 1]);
const event = new BigInt64Array([30n, 10n, 31n, 20n, 11n]);
kwk.sortKV(day, event, { stable: true });
console.log(day);
console.log(event);
Uint32Array(5) [ 1, 1, 2, 3, 3 ]
BigInt64Array(5) [ 10n, 11n, 20n, 30n, 31n ]
package main
import (
"fmt"
"kwker.io/go/kwker"
)
func main() {
day := []uint32{3, 1, 3, 2, 1}
event := []int64{30, 10, 31, 20, 11}
kwker.SortKVStable(day, event, kwker.Ascending)
fmt.Println(day)
fmt.Println(event)
}
[1 1 2 3 3] [10 11 20 30 31]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] day = {3, 1, 3, 2, 1};
long[] events = {30, 10, 31, 20, 11};
Kwker.sortKVStable(day, events, Kwker.ASCENDING);
System.out.println(Arrays.toString(day));
System.out.println(Arrays.toString(events));
}
}
[1, 1, 2, 3, 3] [10, 11, 20, 30, 31]
using Kwker;
var day = new uint[] { 3, 1, 3, 2, 1 };
var events = new long[] { 30, 10, 31, 20, 11 };
Sorter.SortKVStable(day, events);
Console.WriteLine(string.Join(" ", day));
Console.WriteLine(string.Join(" ", events));
1 1 2 3 3 10 11 20 30 31
Only the first k pairs
partial_sort_kv(keys, values, k) puts the k smallest keys first, in order, each with its value (the k largest
in a descending order). select_kv is the key-value form of select.
import numpy as np
import kwker
latency = np.array([120, 85, 430, 95, 610], dtype=np.uint32)
request = np.array([1, 2, 3, 4, 5], dtype=np.int32)
kwker.partial_sort_kv(latency, request, 2, descending=True)
print(latency[:2], request[:2])
[610 430] [5 3]
use kwker::Order;
fn main() {
let mut latency: [u32; 5] = [120, 85, 430, 95, 610];
let mut request: [i32; 5] = [1, 2, 3, 4, 5];
kwker::partial_sort_kv_by_order(&mut latency, &mut request, 2, Order::DESCENDING);
println!("{:?} {:?}", &latency[..2], &request[..2]);
}
[610, 430] [5, 3]
#include <stdio.h>
#include <kwker.h>
int main(void) {
uint32_t latency[] = {120, 85, 430, 95, 610};
int32_t request[] = {1, 2, 3, 4, 5};
kwker_u32_partial_sort_kv(latency, request, sizeof(int32_t), 5, 2, KWKER_DESCENDING);
printf("%u %u / %d %d\n", latency[0], latency[1], request[0], request[1]);
return 0;
}
610 430 / 5 3
#include <cstdint>
#include <iostream>
#include <vector>
#include <kwker.hpp>
int main() {
std::vector<uint32_t> latency{120, 85, 430, 95, 610};
std::vector<int32_t> request{1, 2, 3, 4, 5};
kwker::partial_sort_kv(latency.data(), request.data(), latency.size(), 2, kwker::Order::descending);
std::cout << latency[0] << ' ' << latency[1] << " / " << request[0] << ' ' << request[1] << '\n';
}
610 430 / 5 3
const kwk = require("kwker");
const latency = new Uint32Array([120, 85, 430, 95, 610]);
const request = new Int32Array([1, 2, 3, 4, 5]);
kwk.partialSortKV(latency, request, 2, { descending: true });
console.log(latency.subarray(0, 2), request.subarray(0, 2));
Uint32Array(2) [ 610, 430 ] Int32Array(2) [ 5, 3 ]
package main
import (
"fmt"
"kwker.io/go/kwker"
)
func main() {
latency := []uint32{120, 85, 430, 95, 610}
request := []int32{1, 2, 3, 4, 5}
kwker.PartialSortKV(latency, request, 2, kwker.Descending)
fmt.Println(latency[:2], request[:2])
}
[610 430] [5 3]
import io.kwker.Kwker;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] latency = {120, 85, 430, 95, 610};
int[] request = {1, 2, 3, 4, 5};
Kwker.partialSortKV(latency, request, 2, Kwker.DESCENDING);
System.out.println(Arrays.toString(Arrays.copyOf(latency, 2)) + " " + Arrays.toString(Arrays.copyOf(request, 2)));
}
}
[610, 430] [5, 3]
using Kwker;
var latency = new uint[] { 120, 85, 430, 95, 610 };
var request = new int[] { 1, 2, 3, 4, 5 };
Sorter.PartialSortKV(latency, request, 2, Order.Descending);
Console.WriteLine(string.Join(" ", latency[..2]) + " " + string.Join(" ", request[..2]));
610 430 5 3
Value types
Values can be any type of 1, 2, 4, 8, 12, 16, 24 or 32 bytes, structs and NumPy structured records included: C takes
the value size in bytes, C++ and Rust take any trivially copyable (Copy) value type, and JavaScript any typed array
of 1, 2, 4 or 8 bytes per element. Keys can be any integer or float type.
Related
- Order and ranking:
argsortwhen you need the order itself. - API reference:
sort_kv