Last active
February 11, 2024 03:56
-
-
Save divi255/ab9e54dc40261187dbcb7805a34b8253 to your computer and use it in GitHub Desktop.
tags to tree Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::BTreeMap; | |
#[macro_use] | |
extern crate bma_benchmark; | |
// here Arc<String> is wanted to be used but for small depth Arc provides additional overhead and | |
// results are lower | |
#[derive(Default)] | |
struct Tree(BTreeMap<String, Tree>); | |
impl Tree { | |
fn to_vec(&self) -> Vec<String> { | |
fn combine_tags_recursive(tree: &Tree, prefix: &[String], tags: &mut Vec<String>) { | |
for (key, members) in &tree.0 { | |
if members.0.is_empty() { | |
let mut tag = prefix.join("."); | |
if !tag.is_empty() { | |
tag.push('.'); | |
} | |
tag.push_str(key); | |
tags.push(tag); | |
} else { | |
let mut pfx = prefix.to_owned(); | |
pfx.push(key.clone()); | |
combine_tags_recursive(members, &pfx, tags); | |
} | |
} | |
} | |
let mut tags = vec![]; | |
combine_tags_recursive(self, &[], &mut tags); | |
tags | |
} | |
} | |
impl<S> From<&[S]> for Tree | |
where | |
S: AsRef<str>, | |
{ | |
fn from(tags: &[S]) -> Self { | |
fn fill_tree_recursive(tag: &str, tree: &mut Tree) { | |
let mut sp = tag.splitn(2, '.'); | |
let parent = sp.next().unwrap(); | |
if let Some(child) = sp.next() { | |
fill_tree_recursive( | |
child, | |
tree.0.entry(parent.to_owned()).or_insert(Tree::default()), | |
); | |
} else { | |
tree.0.insert(parent.to_owned(), Tree::default()); | |
} | |
} | |
let mut tree = Tree::default(); | |
for tag in tags { | |
fill_tree_recursive(tag.as_ref(), &mut tree); | |
} | |
tree | |
} | |
} | |
fn main() { | |
let n = 10; | |
let mut tags = Vec::with_capacity(100_000); | |
for a in 0..10 { | |
for b in 0..10 { | |
for c in 0..10 { | |
for d in 0..10 { | |
for e in 0..10 { | |
tags.push(format!( | |
"tagname_a{}.tagname_b{}.tagname_c{}.tagname_d{}.tagname_e{}", | |
a, b, c, d, e | |
)); | |
} | |
} | |
} | |
} | |
} | |
dbg!(tags.len()); | |
benchmark_start!(); | |
for _ in 0..n { | |
let tree: Tree = tags.as_slice().into(); | |
let result = tree.to_vec(); | |
assert_eq!(result.len(), tags.len()); | |
} | |
benchmark_print!(n); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment