{"id":15010269,"url":"https://github.com/clojure/data.priority-map","last_synced_at":"2025-05-15T21:06:55.331Z","repository":{"id":1593978,"uuid":"2124498","full_name":"clojure/data.priority-map","owner":"clojure","description":"Clojure priority map data structure","archived":false,"fork":false,"pushed_at":"2024-07-15T17:57:14.000Z","size":141,"stargazers_count":189,"open_issues_count":0,"forks_count":18,"subscribers_count":33,"default_branch":"master","last_synced_at":"2025-04-08T02:41:52.761Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"wurmlab/sequenceserver","license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clojure.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2011-07-29T15:25:43.000Z","updated_at":"2025-03-28T03:13:50.000Z","dependencies_parsed_at":"2024-02-19T20:35:00.560Z","dependency_job_id":"6e321425-c36a-4100-b5e4-5a5fef020d93","html_url":"https://github.com/clojure/data.priority-map","commit_stats":{"total_commits":73,"total_committers":7,"mean_commits":"10.428571428571429","dds":0.6301369863013699,"last_synced_commit":"603d69e5cbdac74bcdcd7b095824f88ade630edf"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojure%2Fdata.priority-map","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojure%2Fdata.priority-map/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojure%2Fdata.priority-map/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojure%2Fdata.priority-map/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clojure","download_url":"https://codeload.github.com/clojure/data.priority-map/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254422761,"owners_count":22068678,"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":[],"created_at":"2024-09-24T19:33:16.771Z","updated_at":"2025-05-15T21:06:55.309Z","avatar_url":"https://github.com/clojure.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# clojure.data.priority-map\n\nA priority map is very similar to a sorted map,\nbut whereas a sorted map produces a\nsequence of the entries sorted by key, a priority\nmap produces the entries sorted by value.\n\nIn addition to supporting all the functions a\nsorted map supports, a priority map\ncan also be thought of as a queue of [item priority] pairs.\nTo support usage as a versatile priority queue,\npriority maps also support conj/peek/pop operations.\n\n## Releases and Dependency Information\n\nThis project follows the version scheme MAJOR.MINOR.PATCH where each component provides some relative indication of the size of the change, but does not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names).\n\nLatest stable release is 1.2.0\n\n[CLI/`deps.edn`](https://clojure.org/reference/deps_edn) dependency information:\n```clojure\norg.clojure/data.priority-map {:mvn/version \"1.2.0\"}\n```\n\n[Leiningen](https://github.com/technomancy/leiningen) dependency information:\n\n    [org.clojure/data.priority-map \"1.2.0\"]\n\n[Maven](https://maven.apache.org/) dependency information:\n\n    \u003cdependency\u003e\n      \u003cgroupId\u003eorg.clojure\u003c/groupId\u003e\n      \u003cartifactId\u003edata.priority-map\u003c/artifactId\u003e\n      \u003cversion\u003e1.2.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\n\n## Usage\n\nThe standard way to construct a priority map is with priority-map:\n\n    user=\u003e (require '[clojure.data.priority-map :refer [priority-map]])\n    nil\n    user=\u003e (def p (priority-map :a 2 :b 1 :c 3 :d 5 :e 4 :f 3))\n    #'user/p\n\n    user=\u003e p\n    {:b 1, :a 2, :c 3, :f 3, :e 4, :d 5}\n\nSo :b has priority 1, :a has priority 2, and so on.\nNotice how the priority map prints in an order sorted by its priorities (i.e., the map's values)\n\nWe can use assoc to assign a priority to a new item:\n\n    user=\u003e (assoc p :g 1)\n    {:b 1, :g 1, :a 2, :c 3, :f 3, :e 4, :d 5}\n\nor to assign a new priority to an extant item:\n\n    user=\u003e (assoc p :c 4)\n    {:b 1, :a 2, :f 3, :c 4, :e 4, :d 5}\n\nWe can remove an item from the priority map:\n\n    user=\u003e (dissoc p :e)\n    {:b 1, :a 2, :c 3, :f 3, :d 5}\n\nAn alternative way to add to the priority map is to conj a [item priority] pair:\n\n    user=\u003e (conj p [:g 0])\n    {:g 0, :b 1, :a 2, :c 3, :f 3, :e 4, :d 5}\n\nor use into:\n\n    user=\u003e (into p [[:g 0] [:h 1] [:i 2]])\n    {:g 0, :b 1, :h 1, :a 2, :i 2, :c 3, :f 3, :e 4, :d 5}\n\nPriority maps are countable:\n\n    user=\u003e (count p)\n    6\n\nLike other maps, equivalence is based not on type, but on contents.\nIn other words, just as a sorted-map can be equal to a hash-map,\nso can a priority-map.\n\n    user=\u003e (= p {:b 1, :a 2, :c 3, :f 3, :e 4, :d 5})\n    true\n\nYou can test them for emptiness:\n\n    user=\u003e (empty? (priority-map))\n    true\n\n    user=\u003e (empty? p)\n    false\n\nYou can test whether an item is in the priority map:\n\n    user=\u003e (contains? p :a)\n    true\n\n    user=\u003e (contains? p :g)\n    false\n\nIt is easy to look up the priority of a given item, using any of the standard map mechanisms:\n\n    user=\u003e (get p :a)\n    2\n\n    user=\u003e (get p :g 10)\n    10\n\n    user=\u003e (p :a)\n    2\n\n    user=\u003e (:a p)\n    2\n\nPriority maps derive much of their utility by providing priority-based seq.\nNote that no guarantees are made about the order in which items of the same priority appear.\n\n    user=\u003e (seq p)\n    ([:b 1] [:a 2] [:c 3] [:f 3] [:e 4] [:d 5])\n\nBecause no guarantees are made about the order of same-priority items, note that\nrseq might not be an exact reverse of the seq.  It is only guaranteed to be in\ndescending order.\n\n    user=\u003e (rseq p)\n    ([:d 5] [:e 4] [:c 3] [:f 3] [:a 2] [:b 1])\n\nThis means first/rest/next/for/map/etc. all operate in priority order.\n\n    user=\u003e (first p)\n    [:b 1]\n\n    user=\u003e (rest p)\n    ([:a 2] [:c 3] [:f 3] [:e 4] [:d 5])\n\nPriority maps also support subseq and rsubseq, however, *you must use the subseq and rsubseq\ndefined in the clojure.data.priority-map namespace*, which patches longstanding JIRA issue\n[CLJ-428](https://clojure.atlassian.net/browse/CLJ-428).  These patched versions\nof subseq and rsubseq will work on Clojure's other sorted collections as well, so you can\nuse them as a drop-in replacement for the subseq and rsubseq found in core.\n\n\tuser=\u003e (subseq p \u003c 3)\n\t([:b 1] [:a 2])\n\n\tuser=\u003e (subseq p \u003e= 3)\n\t([:c 3] [:f 3] [:e 4] [:d 5])\n\n   \tuser=\u003e (subseq p \u003e= 2 \u003c 4)\n\t([:a 2] [:c 3] [:f 3])\n\n\tuser=\u003e (rsubseq p \u003c 4)\n\t([:c 3] [:f 3] [:a 2] [:b 1])\n\n\tuser=\u003e (rsubseq p \u003e= 4)\n\t([:d 5] [:e 4])\n\nPriority maps support metadata:\n\n    user=\u003e (meta (with-meta p {:extra :info}))\n    {:extra :info}\n\nBut perhaps most importantly, priority maps can also function as priority queues.\npeek, like first, gives you the first [item priority] pair in the collection.\npop removes the first [item priority] from the collection.\n(Note that unlike rest, which returns a seq, pop returns a priority map).\n\n    user=\u003e (peek p)\n    [:b 1]\n\n    user=\u003e (pop p)\n    {:a 2, :c 3, :f 3, :e 4, :d 5}\n    \nInternally, priority maps maintain a sorted map from each priority to the set \nof items with that priority.  You can access that sorted map with the function\npriority-\u003eset-of-items.\n\n\tuser=\u003e (priority-\u003eset-of-items p)\n\t{1 #{:b}, 2 #{:a}, 3 #{:c :f}, 4 #{:e}, 5 #{:d}}\n\nIt is possible to build a priority map with a custom comparator:\n\n    user=\u003e (priority-map-by \u003e :a 1 :b 2 :c 3)\n    {:c 3, :b 2, :a 1}\n\nSometimes, it is desirable to have a map where the values contain more information\nthan just the priority.  For example, let's say you want a map like:\n\n    {:a [2 :apple], :b [1 :banana], :c [3 :carrot]}\n\nand you want to sort the map by the numeric priority found in the pair.\n\nA common mistake is to try to solve this with a custom comparator:\n\n    (priority-map-by\n      (fn [[priority1 _] [priority2 _]] (\u003c priority1 priority2))\n      :a [2 :apple], :b [1 :banana], :c [3 :carrot])\n\nThis will not work!  Although it may appear to work with these particular values, it is not safe.\nIn Clojure, like Java, all comparators must be *total orders*,\nmeaning that you can't have a \"tie\" unless the objects you are comparing are\nin fact equal.  The above comparator breaks that rule because objects such as\n`[2 :apple]` and `[2 :apricot]` would tie, but are not equal.\n\nThe correct way to construct such a priority map is by specifying a keyfn, which is used\nto compute or extract the true priority from the priority map's vals. (Note: It might seem a little odd\nthat the priority-extraction function is called a *key*fn, even though it is applied to the\nmap's values.  This terminology is based on the docstring of clojure.core/sort-by, which\nuses `keyfn` for the function which computes the *sort keys*.)\n\nIn the above example,\n\n    user=\u003e (priority-map-keyfn first :a [2 :apple], :b [1 :banana], :c [3 :carrot])\n    {:b [1 :banana], :a [2 :apple], :c [3 :carrot]}\n\nYou can also combine a keyfn with a comparator that operates on the extracted priorities:\n\n    user=\u003e (priority-map-keyfn-by first \u003e :a [2 :apple], :b [1 :banana], :c [3 :carrot])\n    {:c [3 :carrot], :a [2 :apple], :b [1 :banana]}\n\nsubseq and rsubseq respect the keyfn and/or comparator:\n\n\tuser=\u003e (subseq (priority-map-keyfn first :a [2 :apple], :b [1 :banana], :c [3 :carrot]) \u003c= 2)\n\t([:b [1 :banana]] [:a [2 :apple]])\n\n## License\n\nCopyright (C) Mark Engelberg, Rich Hickey \u0026 contributors\n\nDistributed under the Eclipse Public License, the same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclojure%2Fdata.priority-map","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclojure%2Fdata.priority-map","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclojure%2Fdata.priority-map/lists"}