{"id":15659646,"url":"https://github.com/posener/order","last_synced_at":"2025-05-05T19:41:58.817Z","repository":{"id":57521588,"uuid":"250747660","full_name":"posener/order","owner":"posener","description":"More readable and easier ordering and comparison tasks","archived":false,"fork":false,"pushed_at":"2020-04-21T19:57:33.000Z","size":36,"stargazers_count":21,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-30T23:05:43.670Z","etag":null,"topics":["binary-search","comparable","compare","condition","go","golang","max","min","min-max","order","partition","pivot","search","select","sort"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/posener.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-28T08:32:15.000Z","updated_at":"2024-02-27T08:57:29.000Z","dependencies_parsed_at":"2022-09-26T18:01:19.732Z","dependency_job_id":null,"html_url":"https://github.com/posener/order","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Forder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Forder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Forder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Forder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/posener","download_url":"https://codeload.github.com/posener/order/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252563844,"owners_count":21768530,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binary-search","comparable","compare","condition","go","golang","max","min","min-max","order","partition","pivot","search","select","sort"],"created_at":"2024-10-03T13:17:59.617Z","updated_at":"2025-05-05T19:41:58.800Z","avatar_url":"https://github.com/posener.png","language":"Go","readme":"# order\n\n[![codecov](https://codecov.io/gh/posener/order/branch/master/graph/badge.svg)](https://codecov.io/gh/posener/order)\n[![GoDoc](https://img.shields.io/badge/pkg.go.dev-doc-blue)](http://pkg.go.dev/github.com/posener/order)\n\nPackage order enables easier ordering and comparison tasks.\n\nThis package provides functionality to easily define and apply order on values. It works out of\nthe box for most primitive types and their pointer versions, and enable order of any object using\n[three-way comparison](https://en.wikipedia.org/wiki/Three-way_comparison) with a given\n`func(T, T) int` function, or by implementing the generic interface: `func (T) Compare(T) int`.\n\nSupported Tasks:\n\n* [x] `Sort` / `SortStable` - sort a slice.\n\n* [x] `Search` - binary search for a value in a slice.\n\n* [x] `MinMax` - get indices of minimal and maximal values of a slice.\n\n* [X] `Is` - get a comparable object for more readable code.\n\n+ [x] `Select` - get the K'th greatest value of a slice.\n\n* [x] `IsSorted` / `IsStrictSorted` - check if a slice is sorted.\n\n## Types and Values\n\nOrder between values can be more forgiving than strict comparison. This library allows sensible\ntype conversions. A type `U` can be used in order function of type `T` in the following cases:\n\n* `U` is a pointer (or pointers chain) to a `T`.\n\n* `T` is a pointer (or pointers chain) to a `U`.\n\n* `T` and `U` are of the same kind.\n\n* `T` and `U` are of the same number kind group (int?, uint?, float?, complex?) and `U`'s bits\nnumber is less or equal to `T`'s bits number.\n\n* `U` and `T` are assignable structs.\n\nRead more about this package in this [blog post](https://posener.github.io/order).\n\n## Usage\n\nUsing this library might be less type safe - because of the usage of interfaces API, and less\nefficient - because of the use of reflection. On the other hand, this library reduce chances for\nerrors by providing a well tested code and more readable code. See below how some order tasks\ncan be translated to be used by this library.\n\n```diff\n type person struct {\n \tname string\n \tage  int\n }\n\n var persons []person\n\n // Sort persons (by name and then by age)\n-lessPersons := func(i, j int) bool {\n-\tnameCmp := strings.Compare(persons[i].name, \"joe\")\n-\tif nameCmp == 0 {\n-\t\treturn persons[i].age \u003c persons[i].age\n-\t}\n-\treturn nameCmp \u003c 0\n-}\n-sort.Slice(persons, lessPersons)\n+orderPersons := order.By(\n+\tfunc(a, b person) int { return strings.Compare(a.name, b.name) },\n+\tfunc(a, b person) int { return a.age - b.age },\n+)\n+orderPersons.Sort(persons)\n\n // Search persons for \"joe\" at age 42:\n-searchPersons := func(int i) bool {\n-\tnameCmp := strings.Compare(persons[i].name, \"joe\")\n-\tif nameCmp == 0 {\n-\t\treturn persons[i].age \u003e= 42\n-\t}\n-\treturn nameCmp \u003e 0 {\n-}\n-i := sort.Search(persons, searchPersons)\n-// Standard library search does not guarantee equality, we should check:\n-if i \u003e= len(persons) || persons[i].name != \"joe\" || persons[i].age != 42 {\n-\ti := -1\n-}\n+i := orderPersons.Search(persons, person{name: \"joe\", age: 42})\n\n // Another way is that person will implement a `Compare(T) int` method, and the order object\n // will know how to handle it:\n+func (p person) Compare(other person) int { ... }\n+order.Search(persons, person{name: \"joe\", age: 42})\n\n // Conditions can also be defined on comparable types:\n var t, start, end time.Time\n-if (t.After(start) || t.Equal(start)) \u0026\u0026 t.Before(end) { ... }\n+if isT := order.Is(t); isT.GreaterEqual(start) \u0026\u0026 isT.Less(end) { ... }\n```\n\n## Examples\n\nA simple example that shows how to use the order library with different basic types.\n\n```golang\n// The order function can be used to check values equality:\nfmt.Println(\"now \u003e one-second-ago ?\",\n    Is(time.Now()).Greater(time.Now().Add(-time.Second)))\nfmt.Println(\"foo == bar ?\",\n    Is(\"foo\").Equal(\"bar\"))\n\n// Checking if a value is within a range:\nif is := Is(3); is.GreaterEqual(3) \u0026\u0026 is.Less(4) {\n    fmt.Println(\"3 is in [3,4)\")\n}\n```\n\n Output:\n\n```\nnow \u003e one-second-ago ? true\nfoo == bar ? false\n3 is in [3,4)\n```\n\n### Comparable\n\nA type may implement a `func (t T) Compare(other T) int` function. In this case it could be just\nused with the order package functions.\n\n```golang\noranges := []orange{5, 2, 24}\nSort(oranges)\nfmt.Println(oranges)\n```\n\n Output:\n\n```\n[2 5 24]\n```\n\n### Complex\n\nAn example of ordering struct with multiple fields with different priorities.\n\n```golang\n// Define a struct with fields of different types.\ntype person struct {\n    name string\n    age  int\n}\n// Order persons: first by name and then by age - reversed.\norderPersons := By(\n    func(a, b person) int { return strings.Compare(a.name, b.name) },\n    func(a, b person) int { return a.age - b.age },\n).Reversed()\n\n// Sort a list of persons in reversed order.\nlist := []person{\n    {\"Bar\", 10},\n    {\"Foo\", 10},\n    {\"Bar\", 11},\n}\norderPersons.Sort(list)\nfmt.Println(\"Reversed:\", list)\n\n// Search for a specific person in the sorted list.\nfmt.Println(\"Index of {Foo 10}:\", orderPersons.Search(list, person{\"Foo\", 10}))\n```\n\n Output:\n\n```\nReversed: [{Foo 10} {Bar 11} {Bar 10}]\nIndex of {Foo 10}: 0\n```\n\n### SliceOperations\n\n```golang\n// The order function can be used to sort lists:\nlist := []int{2, 1, 3}\nSort(list)\nfmt.Println(\"Sorted:\", list)\n\n// Values can be looked up in sorted lists using a binary search:\nfmt.Println(\"Index of 2:\", Search(list, 2))\n\n// Get the minimal and maximal values:\nminI, maxI := MinMax(list)\nfmt.Printf(\"Min: %d, max: %d\\n\", list[minI], list[maxI])\n\n// Get the k'th greatest value:\nSelect(list, len(list)/2)\nfmt.Printf(\"Median: %d\\n\", list[1])\n```\n\n Output:\n\n```\nSorted: [1 2 3]\nIndex of 2: 1\nMin: 1, max: 3\nMedian: 2\n```\n\n---\nReadme created from Go doc with [goreadme](https://github.com/posener/goreadme)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposener%2Forder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fposener%2Forder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposener%2Forder/lists"}