{"id":13822484,"url":"https://github.com/laysakura/trie-rs","last_synced_at":"2025-04-05T05:08:18.247Z","repository":{"id":53108280,"uuid":"183540567","full_name":"laysakura/trie-rs","owner":"laysakura","description":"Memory efficient trie (prefix tree) library based on LOUDS","archived":false,"fork":false,"pushed_at":"2024-08-20T01:24:20.000Z","size":4896,"stargazers_count":96,"open_issues_count":8,"forks_count":13,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-30T07:06:48.958Z","etag":null,"topics":["louds","rust","succinct-data-structure","trie"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/trie-rs","language":"Rust","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/laysakura.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","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":"2019-04-26T02:14:54.000Z","updated_at":"2024-10-25T07:56:41.000Z","dependencies_parsed_at":"2024-01-18T03:42:17.740Z","dependency_job_id":"9ac57008-6bfb-4546-9f87-ba2e3ebfb5c0","html_url":"https://github.com/laysakura/trie-rs","commit_stats":{"total_commits":194,"total_committers":4,"mean_commits":48.5,"dds":"0.17525773195876293","last_synced_commit":"89c8a67a02792a21a932c807316da77d8973da7d"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laysakura%2Ftrie-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laysakura%2Ftrie-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laysakura%2Ftrie-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laysakura%2Ftrie-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/laysakura","download_url":"https://codeload.github.com/laysakura/trie-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289428,"owners_count":20914464,"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":["louds","rust","succinct-data-structure","trie"],"created_at":"2024-08-04T08:02:02.181Z","updated_at":"2025-04-05T05:08:18.226Z","avatar_url":"https://github.com/laysakura.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# trie-rs\n\nMemory efficient trie (prefix tree) and map library based on LOUDS.\n\n[Master API Docs](https://laysakura.github.io/trie-rs/trie_rs/)\n|\n[Released API Docs](https://docs.rs/crate/trie-rs)\n|\n[Benchmark Results](https://laysakura.github.io/trie-rs/criterion/report/)\n|\n[Changelog](https://github.com/laysakura/trie-rs/blob/master/CHANGELOG.md)\n\n[![GitHub Actions Status](https://github.com/laysakura/trie-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/laysakura/trie-rs/actions)\n[![Crates.io Version](https://img.shields.io/crates/v/trie-rs.svg)](https://crates.io/crates/trie-rs)\n[![Crates.io Downloads](https://img.shields.io/crates/d/trie-rs.svg)](https://crates.io/crates/trie-rs)\n[![Minimum rustc version](https://img.shields.io/badge/rustc-1.56+-lightgray.svg)](https://github.com/laysakura/trie-rs#rust-version-supports)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/laysakura/trie-rs/blob/master/LICENSE-MIT)\n[![License: Apache 2.0](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](https://github.com/laysakura/trie-rs/blob/master/LICENSE-APACHE)\n\n## Quickstart\n\nTo use trie-rs, add the following to your `Cargo.toml` file:\n\n```toml\n[dependencies]\ntrie-rs = \"0.4.2\"\n```\n\n### Usage Overview\n```rust\nuse std::str;\nuse trie_rs::TrieBuilder;\n\nlet mut builder = TrieBuilder::new();  // Inferred `TrieBuilder\u003cu8\u003e` automatically\nbuilder.push(\"すし\");\nbuilder.push(\"すしや\");\nbuilder.push(\"すしだね\");\nbuilder.push(\"すしづめ\");\nbuilder.push(\"すしめし\");\nbuilder.push(\"すしをにぎる\");\nbuilder.push(\"すし\");  // Word `push`ed twice is just ignored.\nbuilder.push(\"🍣\");\n\nlet trie = builder.build();\n\n// exact_match(): Find a word exactly match to query.\nassert_eq!(trie.exact_match(\"すし\"), true);\nassert_eq!(trie.exact_match(\"🍣\"), true);\nassert_eq!(trie.exact_match(\"🍜\"), false);\n\n// predictive_search(): Find words which include `query` as their prefix.\nlet results_in_u8s: Vec\u003cVec\u003cu8\u003e\u003e = trie.predictive_search(\"すし\").collect();\nlet results_in_str: Vec\u003cString\u003e = trie.predictive_search(\"すし\").collect();\nassert_eq!(\n    results_in_str,\n    vec![\n        \"すし\",\n        \"すしだね\",\n        \"すしづめ\",\n        \"すしめし\",\n        \"すしや\",\n        \"すしをにぎる\"\n    ]  // Sorted by `Vec\u003cu8\u003e`'s order\n);\n\n// common_prefix_search(): Find words which is included in `query`'s prefix.\nlet results_in_u8s: Vec\u003cVec\u003cu8\u003e\u003e = trie.common_prefix_search(\"すしや\").collect();\nlet results_in_str: Vec\u003cString\u003e = trie.common_prefix_search(\"すしや\").collect();\nassert_eq!(\n    results_in_str,\n    vec![\n        \"すし\",\n        \"すしや\",\n    ]  // Sorted by `Vec\u003cu8\u003e`'s order\n);\n```\n\n### Using with Various Data Types\n`TrieBuilder` is implemented using generic type like following:\n\n```ignore\nimpl\u003cLabel: Ord\u003e TrieBuilder\u003cLabel\u003e {\n    ...\n    pub fn push\u003cArr: AsRef\u003c[Label]\u003e\u003e(\u0026mut self, word: Arr) where Label: Clone { ... }\n    ...\n}\n```\n\nIn the above `Usage Overview` example, we used `Label=u8, Arr=\u0026str`. If\n`Label` does not implement `Clone`, use\n[`insert()`][crate::trie::TrieBuilder::insert].\n\nHere shows other `Label` and `Arr` type examples.\n\n#### `Label=\u0026str, Arr=Vec\u003c\u0026str\u003e`\nSay `Label` is English words and `Arr` is English phrases.\n\n```rust\nuse trie_rs::TrieBuilder;\n\nlet mut builder = TrieBuilder::new();\nbuilder.push(vec![\"a\", \"woman\"]);\nbuilder.push(vec![\"a\", \"woman\", \"on\", \"the\", \"beach\"]);\nbuilder.push(vec![\"a\", \"woman\", \"on\", \"the\", \"run\"]);\n\nlet trie = builder.build();\n\nassert_eq!(\n    trie.exact_match(vec![\"a\", \"woman\", \"on\", \"the\", \"beach\"]),\n    true\n);\nlet r: Vec\u003cVec\u003c\u0026str\u003e\u003e = trie.predictive_search(vec![\"a\", \"woman\", \"on\"]).collect();\nassert_eq!(\n    r,\n    vec![\n        [\"a\", \"woman\", \"on\", \"the\", \"beach\"],\n        [\"a\", \"woman\", \"on\", \"the\", \"run\"],\n    ],\n);\nlet s: Vec\u003cVec\u003c\u0026str\u003e\u003e = trie.common_prefix_search(vec![\"a\", \"woman\", \"on\", \"the\", \"beach\"]).collect();\nassert_eq!(\n    s,\n    vec![vec![\"a\", \"woman\"], vec![\"a\", \"woman\", \"on\", \"the\", \"beach\"]],\n);\n```\n\n#### `Label=u8, Arr=[u8; n]`\nSay `Label` is a digit in Pi (= 3.14...) and Arr is a window to separate pi's digit by 10.\n\n```rust\nuse trie_rs::TrieBuilder;\n\nlet mut builder = TrieBuilder::\u003cu8\u003e::new(); // Pi = 3.14...\n\nbuilder.push([1, 4, 1, 5, 9, 2, 6, 5, 3, 5]);\nbuilder.push([8, 9, 7, 9, 3, 2, 3, 8, 4, 6]);\nbuilder.push([2, 6, 4, 3, 3, 8, 3, 2, 7, 9]);\nbuilder.push([6, 9, 3, 9, 9, 3, 7, 5, 1, 0]);\nbuilder.push([5, 8, 2, 0, 9, 7, 4, 9, 4, 4]);\nbuilder.push([5, 9, 2, 3, 0, 7, 8, 1, 6, 4]);\nbuilder.push([0, 6, 2, 8, 6, 2, 0, 8, 9, 9]);\nbuilder.push([8, 6, 2, 8, 0, 3, 4, 8, 2, 5]);\nbuilder.push([3, 4, 2, 1, 1, 7, 0, 6, 7, 9]);\nbuilder.push([8, 2, 1, 4, 8, 0, 8, 6, 5, 1]);\nbuilder.push([3, 2, 8, 2, 3, 0, 6, 6, 4, 7]);\nbuilder.push([0, 9, 3, 8, 4, 4, 6, 0, 9, 5]);\nbuilder.push([5, 0, 5, 8, 2, 2, 3, 1, 7, 2]);\nbuilder.push([5, 3, 5, 9, 4, 0, 8, 1, 2, 8]);\n\nlet trie = builder.build();\n\nassert_eq!(trie.exact_match([5, 3, 5, 9, 4, 0, 8, 1, 2, 8]), true);\n\nlet t: Vec\u003cVec\u003cu8\u003e\u003e = trie.predictive_search([3]).collect();\nassert_eq!(\n    t,\n    vec![\n        [3, 2, 8, 2, 3, 0, 6, 6, 4, 7],\n        [3, 4, 2, 1, 1, 7, 0, 6, 7, 9],\n    ],\n);\nlet u: Vec\u003cVec\u003cu8\u003e\u003e = trie.common_prefix_search([1, 4, 1, 5, 9, 2, 6, 5, 3, 5]).collect();\nassert_eq!(\n    u,\n    vec![[1, 4, 1, 5, 9, 2, 6, 5, 3, 5]],\n);\n```\n\n### Trie Map Usage\n\nTo store a value with each word, use `trie_rs::map::{Trie, TrieBuilder}`.\n\n```rust\nuse std::str;\nuse trie_rs::map::TrieBuilder;\n\nlet mut builder = TrieBuilder::new();  // Inferred `TrieBuilder\u003cu8, u8\u003e` automatically\nbuilder.push(\"すし\", 0);\nbuilder.push(\"すしや\", 1);\nbuilder.push(\"すしだね\", 2);\nbuilder.push(\"すしづめ\", 3);\nbuilder.push(\"すしめし\", 4);\nbuilder.push(\"すしをにぎる\", 5);\nbuilder.push(\"すし\", 6);  // Word `push`ed twice uses last value.\nbuilder.push(\"🍣\", 7);\n\nlet mut trie = builder.build();\n\n// exact_match(): Find a word exactly match to query.\nassert_eq!(trie.exact_match(\"すし\"), Some(\u00266));\nassert_eq!(trie.exact_match(\"🍣\"), Some(\u00267));\nassert_eq!(trie.exact_match(\"🍜\"), None);\n\n// Values can be modified.\nlet v = trie.exact_match_mut(\"🍣\").unwrap();\n*v = 8;\nassert_eq!(trie.exact_match(\"🍣\"), Some(\u00268));\n```\n\n### Incremental Search\n\nFor interactive applications, one can use an incremental search to get the\nbest performance. See [IncSearch][crate::inc_search::IncSearch].\n\n```rust\nuse std::str;\nuse trie_rs::{TrieBuilder, inc_search::Answer};\n\nlet mut builder = TrieBuilder::new();  // Inferred `TrieBuilder\u003cu8, u8\u003e` automatically\nbuilder.push(\"ab\");\nbuilder.push(\"すし\");\nbuilder.push(\"すしや\");\nbuilder.push(\"すしだね\");\nbuilder.push(\"すしづめ\");\nbuilder.push(\"すしめし\");\nbuilder.push(\"すしをにぎる\");\nlet trie = builder.build();\nlet mut search = trie.inc_search();\n\n// Query by the byte.\nassert_eq!(search.query(\u0026b'a'), Some(Answer::Prefix));\nassert_eq!(search.query(\u0026b'c'), None);\nassert_eq!(search.query(\u0026b'b'), Some(Answer::Match));\n\n// Reset the query to go again.\nsearch.reset();\n\n// For unicode its easier to use .query_until().\nassert_eq!(search.query_until(\"す\"), Ok(Answer::Prefix));\nassert_eq!(search.query_until(\"し\"), Ok(Answer::PrefixAndMatch));\nassert_eq!(search.query_until(\"や\"), Ok(Answer::Match));\nassert_eq!(search.query(\u0026b'a'), None);\nassert_eq!(search.query_until(\"a\"), Err(0));\n\nsearch.reset();\nassert_eq!(search.query_until(\"ab-NO-MATCH-\"), Err(2)); // No match on byte at index 2.\n```\n\n## Features\n- **Generic type support**: As the above examples show, trie-rs can be used for searching not only UTF-8 string but also other data types.\n- **Based on [louds-rs](https://crates.io/crates/louds-rs)**, which is fast, parallelized, and memory efficient.\n- **Latest benchmark results are always accessible**: trie-rs is continuously benchmarked in GitHub Actions using [Criterion.rs](https://crates.io/crates/criterion). Graphical benchmark results are published [here](https://laysakura.github.io/trie-rs/criterion/report/).\n- `map::Trie` associates a `Value` with each entry.\n- `Value` does not require any traits.\n- `Label: Clone` not required to create `Trie\u003cLabel\u003e` but useful for many reifying search operations like `predictive_search()`.\n- Many search operations are implemented via iterators which are lazy, require less memory, and can be short circuited.\n- Incremental search available for \"online\" applications, i.e., searching one `Label` at a time.\n\n## Cargo features\n\n- \"rayon\"\n\nEnables [rayon](https://crates.io/crates/rayon) a data parallelism library.\n\n- \"mem_dbg\"\n\nCan determine the size in bytes of nested data structures like the trie itself.\n\n- \"serde\"\n\nCan serialize and deserialize the trie.\n\n## Acknowledgments\n[`edict.furigana`](https://github.com/laysakura/trie-rs/blob/master/benches/edict.furigana) is used for benchmark.\nThis file is constructed in the following step:\n\n1. Download `edict.gz` from [EDICT](http://www.edrdg.org/jmdict/edict.html).\n2. Convert it from original EUC into UTF-8.\n3. Translate it into CSV file with [edict-to-csv](https://pypi.org/project/edict-to-csv/).\n4. Extract field $1 for Hiragana/Katakana words, and field $3 for other (like Kanji) words.\n5. Translate Katakana into Hiragana with [kana2hira](https://github.com/ShellShoccar-jpn/misc-tools/blob/master/kata2hira).\n\nMany thanks for these dictionaries and tools.\n\n## Versions\ntrie-rs uses [semantic versioning](http://semver.org/spec/v2.0.0.html).\n\nSince current major version is _0_, minor version update might involve breaking public API change (although it is carefully avoided).\n\n## Rust Version Supports\n\ntrie-rs is continuously tested with these Rust versions in with the github CI:\n\n- 1.75.0 with all features\n- 1.67.0 with no features\n- Latest stable version\n\nSo it is expected to work with Rust 1.75.0 and any newer versions.\n\nOlder versions may also work but are not tested or guaranteed.\n\n### Earlier Rust Verion Supports\n\nIf support for Rust prior to 1.67.0 is required, trie-rs 0.2.0 supports Rust 1.33.0 and later.\n\n## Contributing\n\nAny kind of pull requests are appreciated.\n\n## License\n\nMIT OR Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaysakura%2Ftrie-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaysakura%2Ftrie-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaysakura%2Ftrie-rs/lists"}