mergesortedslices

package module
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2024 License: Unlicense Imports: 1 Imported by: 0

README

go get github.com/fiatjaf/mergesortedslices

if you have any number of sorted slices you can merge them all in a single sorted slice.

this orders bigger elements first rather than the opposite -- if you want it the other way please copy-paste the code and change.

this sometimes is faster than just mashing them together like a madman and calling `slices.Sort()` then `slices.Reverse()`, but sometimes not.

goos: linux
goarch: amd64
pkg: github.com/fiatjaf/merge-sorted-slices
cpu: AMD Ryzen 3 3200G with Radeon Vega Graphics

BenchmarkMergeVsQuicksort/many-small/mergeall-4                    10000            121018 ns/op
BenchmarkMergeVsQuicksort/many-small/quicksort-4                   30464             38996 ns/op
BenchmarkMergeVsQuicksort/few-big/mergeall-4                       22197             56067 ns/op
BenchmarkMergeVsQuicksort/few-big/quicksort-4                      10000            111113 ns/op
BenchmarkMergeVsQuicksort/fewest-big/mergeall-4                    38775             37689 ns/op
BenchmarkMergeVsQuicksort/fewest-big/quicksort-4                   15337             91172 ns/op
BenchmarkMergeVsQuicksort/many-big/mergeall-4                        409           2578229 ns/op
BenchmarkMergeVsQuicksort/many-big/quicksort-4                       904           1616955 ns/op
BenchmarkMergeVsQuicksort/few-small/mergeall-4                    797331              2328 ns/op
BenchmarkMergeVsQuicksort/few-small/quicksort-4                   600583              2941 ns/op

for some reason using a custom comparator is significantly slower than using the hardcoded `cmp.Compare()` -- even when you actually pass in `cmp.Compare` as an argument. don't ask me why. the same performance hit (or bigger) also affects `slices.SortFunc()`.

BenchmarkMergeVsQuicksortFunc/many-small/mergeall-4                 9319            151554 ns/op
BenchmarkMergeVsQuicksortFunc/many-small/quicksort-4               14011             93110 ns/op
BenchmarkMergeVsQuicksortFunc/few-big/mergeall-4                   14103             82564 ns/op
BenchmarkMergeVsQuicksortFunc/few-big/quicksort-4                   7546            224849 ns/op
BenchmarkMergeVsQuicksortFunc/fewest-big/mergeall-4                21457             53450 ns/op
BenchmarkMergeVsQuicksortFunc/fewest-big/quicksort-4                9021            181349 ns/op
BenchmarkMergeVsQuicksortFunc/many-big/mergeall-4                    290           4231061 ns/op
BenchmarkMergeVsQuicksortFunc/many-big/quicksort-4                   406           2704375 ns/op
BenchmarkMergeVsQuicksortFunc/few-small/mergeall-4                488162              3385 ns/op
BenchmarkMergeVsQuicksortFunc/few-small/quicksort-4               256736              6720 ns/op

this will work better on a smaller number of slices that have a bigger number of sequential values that are not interlaced, i.e.,

merging {1, 2, 4, 6, 7, 8, 13, 16, 19, 20} with {18, 22, 25, 28, 29, 30, 31} will work better than
merging {1, 1, 2, 3, 3, 5, 7, 8, 10, 12, 15} with {1, 2, 4, 5, 6, 9, 11, 13, 14, 16}.

now where it excels is when you need to take just the first N of the values, so you can stop the iteration at some point (which you can't do with quicksort):

BenchmarkMergeVsQuicksortLimit/many-small/mergeall-4               53628             23622 ns/op
BenchmarkMergeVsQuicksortLimit/many-small/quicksort-4              28882             43004 ns/op
BenchmarkMergeVsQuicksortLimit/few-big/mergeall-4                 281392              5951 ns/op
BenchmarkMergeVsQuicksortLimit/few-big/quicksort-4                  9242            115081 ns/op
BenchmarkMergeVsQuicksortLimit/fewest-big/mergeall-4              442494              4093 ns/op
BenchmarkMergeVsQuicksortLimit/fewest-big/quicksort-4              10000            102202 ns/op
BenchmarkMergeVsQuicksortLimit/many-big/mergeall-4                 24458             51888 ns/op
BenchmarkMergeVsQuicksortLimit/many-big/quicksort-4                  639           1568560 ns/op
BenchmarkMergeVsQuicksortLimit/few-small/mergeall-4              1286480              1074 ns/op
BenchmarkMergeVsQuicksortLimit/few-small/quicksort-4              377631              2668 ns/op

---

this may or may not be called a "k-way" merge algorithm.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Merge

func Merge[A cmp.Ordered](all [][]A) []A

Merge take a bunch of simple lists and merges them. They must be ordered otherwise everything will be broken. Merge will order stuff with bigger values first, which is the opposite of what everybody else does. Why? Because that how I needed it to work. It will also expect the given lists to be ordered like that.

func MergeFunc added in v0.0.3

func MergeFunc[A any](all [][]A, cmp func(a, b A) int) []A

MergeFunc is like Merge, but takes a custom comparator. It will still put bigger elements first (but you can pass a comparator that returns reverse values if you want the opposite behavior).

func MergeFuncLimit added in v0.0.4

func MergeFuncLimit[A any](all [][]A, cmp func(a, b A) int, limit int) []A

MergeFuncLimit is like MergeLimit, but with a custom comparator.

func MergeFuncLimitNoEmptyLists added in v0.0.6

func MergeFuncLimitNoEmptyLists[A any](all [][]A, cmp func(a, b A) int, limit int) []A

MergeFuncLimitNoEmptyLists is like MergeLimitNoEmptyLists, but with a custom comparator.

func MergeFuncNoEmptyListsIntoSlice added in v0.0.7

func MergeFuncNoEmptyListsIntoSlice[A any](res []A, all [][]A, cmp func(a, b A) int) []A

MergeFuncNoEmptyListsIntoSlice is like MergeNoEmptyListsIntoSlice, but with a custom comparator.

func MergeLimit added in v0.0.4

func MergeLimit[A cmp.Ordered](all [][]A, limit int) []A

MergeLimit is the same as Merge, but takes a limit. While Merge will order all the items in all the lists MergeLimit will stop when it reaches limit, which means it will be much faster if the limit is smaller than the total count of all items.

func MergeLimitNoEmptyLists added in v0.0.6

func MergeLimitNoEmptyLists[A cmp.Ordered](all [][]A, limit int) []A

MergeLimitNoEmptyLists is the same as MergeLimit, but assumes there are not empty lists, like MergeNoEmptyLists.

func MergeNoEmptyListsIntoSlice added in v0.0.7

func MergeNoEmptyListsIntoSlice[A cmp.Ordered](res []A, all [][]A) []A

MergeNoEmptyListsIntoSlice is the same as MergeLimitNoEmptyLists, but take a slice into which it will insert the results. The slice length will not be increased, its length will be treated as the max limit.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳