Skip to content

Commit 9ec8bec

Browse files
authored
Merge pull request #41 from AuTa/sort
Add sort feature for tree NodeMut
2 parents b8adcd1 + c34461b commit 9ec8bec

File tree

3 files changed

+214
-1
lines changed

3 files changed

+214
-1
lines changed

src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub struct Tree<T> {
5252
/// Node ID.
5353
///
5454
/// Index into a `Tree`-internal `Vec`.
55-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
55+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5656
pub struct NodeId(NonZeroUsize);
5757

5858
impl NodeId {
@@ -935,3 +935,5 @@ impl<T: Display> Display for Tree<T> {
935935
Ok(())
936936
}
937937
}
938+
939+
mod sort;

src/sort.rs

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//! Sorting functionality for tree nodes.
2+
//!
3+
//! This module provides methods for sorting children of a node in a tree.
4+
//! The sorting can be done based on the node values or their indices.
5+
6+
use std::cmp::Ordering;
7+
8+
use crate::{NodeMut, NodeRef};
9+
10+
impl<'a, T: 'a> NodeMut<'a, T> {
11+
/// Sort children by value in ascending order.
12+
///
13+
/// # Examples
14+
///
15+
/// ```rust
16+
/// use ego_tree::tree;
17+
///
18+
/// let mut tree = tree!('a' => { 'd', 'c', 'b' });
19+
/// tree.root_mut().sort();
20+
/// assert_eq!(
21+
/// vec![&'b', &'c', &'d'],
22+
/// tree.root()
23+
/// .children()
24+
/// .map(|n| n.value())
25+
/// .collect::<Vec<_>>(),
26+
/// );
27+
/// ```
28+
pub fn sort(&mut self)
29+
where
30+
T: Ord,
31+
{
32+
self.sort_by(|a, b| a.value().cmp(b.value()));
33+
}
34+
35+
/// Sort children by `NodeRef` in ascending order using a comparison function.
36+
///
37+
/// # Examples
38+
///
39+
/// ```rust
40+
/// use ego_tree::tree;
41+
///
42+
/// let mut tree = tree!('a' => { 'c', 'd', 'b' });
43+
/// tree.root_mut().sort_by(|a, b| b.value().cmp(a.value()));
44+
/// assert_eq!(
45+
/// vec![&'d', &'c', &'b'],
46+
/// tree.root()
47+
/// .children()
48+
/// .map(|n| n.value())
49+
/// .collect::<Vec<_>>(),
50+
/// );
51+
///
52+
/// // Example for sort_by_id.
53+
/// tree.root_mut().sort_by(|a, b| a.id().cmp(&b.id()));
54+
/// assert_eq!(
55+
/// vec![&'c', &'d', &'b'],
56+
/// tree.root()
57+
/// .children()
58+
/// .map(|n| n.value())
59+
/// .collect::<Vec<_>>(),
60+
/// );
61+
/// ```
62+
pub fn sort_by<F>(&mut self, mut compare: F)
63+
where
64+
F: FnMut(NodeRef<T>, NodeRef<T>) -> Ordering,
65+
{
66+
if !self.has_children() {
67+
return;
68+
}
69+
70+
let mut children = {
71+
let this = unsafe { self.tree.get_unchecked(self.id) };
72+
this.children().map(|child| child.id).collect::<Vec<_>>()
73+
};
74+
75+
children.sort_by(|a, b| {
76+
let a = unsafe { self.tree.get_unchecked(*a) };
77+
let b = unsafe { self.tree.get_unchecked(*b) };
78+
compare(a, b)
79+
});
80+
81+
for id in children {
82+
self.append_id(id);
83+
}
84+
}
85+
86+
/// Sort children by `NodeRef`'s key in ascending order using a key extraction function.
87+
///
88+
/// # Examples
89+
///
90+
/// ```rust
91+
/// use ego_tree::tree;
92+
///
93+
/// let mut tree = tree!("1a" => { "2b", "4c", "3d" });
94+
/// tree.root_mut().sort_by_key(|a| a.value().split_at(1).0.parse::<i32>().unwrap());
95+
/// assert_eq!(
96+
/// vec!["2b", "3d", "4c"],
97+
/// tree.root()
98+
/// .children()
99+
/// .map(|n| *n.value())
100+
/// .collect::<Vec<_>>(),
101+
/// );
102+
///
103+
/// // Example for sort_by_id.
104+
/// tree.root_mut().sort_by_key(|n| n.id());
105+
/// assert_eq!(
106+
/// vec![&"2b", &"4c", &"3d"],
107+
/// tree.root()
108+
/// .children()
109+
/// .map(|n| n.value())
110+
/// .collect::<Vec<_>>(),
111+
/// );
112+
/// ```
113+
pub fn sort_by_key<K, F>(&mut self, mut f: F)
114+
where
115+
F: FnMut(NodeRef<T>) -> K,
116+
K: Ord,
117+
{
118+
self.sort_by(|a, b| f(a).cmp(&f(b)));
119+
}
120+
}

tests/sort.rs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::assert_eq;
2+
3+
use ego_tree::tree;
4+
5+
#[test]
6+
fn sort() {
7+
let mut tree = tree!('a' => { 'd' => { 'e', 'f' }, 'c', 'b' });
8+
tree.root_mut().sort();
9+
assert_eq!(
10+
vec![&'b', &'c', &'d'],
11+
tree.root()
12+
.children()
13+
.map(|n| n.value())
14+
.collect::<Vec<_>>(),
15+
);
16+
assert_eq!(
17+
tree.to_string(),
18+
tree!('a' => { 'b', 'c', 'd' => { 'e', 'f' } }).to_string()
19+
);
20+
}
21+
22+
#[test]
23+
fn sort_by() {
24+
let mut tree = tree!('a' => { 'c', 'd', 'b' });
25+
tree.root_mut().sort_by(|a, b| b.value().cmp(a.value()));
26+
assert_eq!(
27+
vec![&'d', &'c', &'b'],
28+
tree.root()
29+
.children()
30+
.map(|n| n.value())
31+
.collect::<Vec<_>>(),
32+
);
33+
34+
let mut tree = tree!('a' => { 'c','d', 'e', 'b' });
35+
tree.root_mut().sort_by(|a, b| b.value().cmp(a.value()));
36+
assert_eq!(
37+
vec![&'e', &'d', &'c', &'b'],
38+
tree.root()
39+
.children()
40+
.map(|n| n.value())
41+
.collect::<Vec<_>>(),
42+
);
43+
}
44+
45+
#[test]
46+
fn sort_by_key() {
47+
let mut tree = tree!("1a" => { "2b", "4c", "3d" });
48+
tree.root_mut()
49+
.sort_by_key(|a| a.value().split_at(1).0.parse::<i32>().unwrap());
50+
assert_eq!(
51+
vec!["2b", "3d", "4c"],
52+
tree.root()
53+
.children()
54+
.map(|n| *n.value())
55+
.collect::<Vec<_>>(),
56+
);
57+
}
58+
59+
#[test]
60+
fn sort_id() {
61+
let mut tree = tree!('a' => { 'd', 'c', 'b' });
62+
tree.root_mut().sort();
63+
assert_ne!(
64+
vec![&'d', &'c', &'b'],
65+
tree.root()
66+
.children()
67+
.map(|n| n.value())
68+
.collect::<Vec<_>>(),
69+
);
70+
tree.root_mut().sort_by_key(|n| n.id());
71+
assert_eq!(
72+
vec![&'d', &'c', &'b'],
73+
tree.root()
74+
.children()
75+
.map(|n| n.value())
76+
.collect::<Vec<_>>(),
77+
);
78+
}
79+
80+
#[test]
81+
fn sort_by_id() {
82+
let mut tree = tree!('a' => { 'd', 'b', 'c' });
83+
tree.root_mut().sort_by(|a, b| b.id().cmp(&a.id()));
84+
assert_eq!(
85+
vec![&'c', &'b', &'d'],
86+
tree.root()
87+
.children()
88+
.map(|n| n.value())
89+
.collect::<Vec<_>>(),
90+
);
91+
}

0 commit comments

Comments
 (0)