Expand description
A data structure that efficiently partitions elements into two distinct sets.
Partition<T> maintains a collection of elements divided into “left” and
“right” partitions, with O(1) pushes, pops, and moves between partitions.
Internally, it uses a partition index to divide a single Vec<T> into two
partitions. Most operations on Vec<T> are supported by Partition<T>.
Partitions are sets, not lists: within each partition, order is not
necessarily preserved. (One could say the elements of a Partition<T>
obey Bose-Einstein statistics.)
§Examples
§Basic Usage
use bose_einstein::Partition;
// create a partition and add elements to both sides
let mut partition = Partition::new();
partition.push_left("apple");
partition.push_left("banana");
partition.push_right("cherry");
partition.push_right("date");
// sort elements for predictable assertions
// (remember: order is not preserved within partitions)
partition.left_mut().sort();
partition.right_mut().sort();
// access elements in each partition
assert_eq!(partition.left(), &["apple", "banana"]);
assert_eq!(partition.right(), &["cherry", "date"]);
// move elements between partitions
let moved = partition.move_to_right();
assert!(moved.is_some()); // we got some element from the left partition
// element should be one of the two we added to the left partition
let moved_val = moved.unwrap();
assert!(moved_val == "apple" || moved_val == "banana");
// get both partitions at once with the convenient partitions() method
let (left, right) = partition.partitions();
assert_eq!(left.len(), 1);
assert_eq!(right.len(), 3);§Using Drain Operations
use bose_einstein::Partition;
let mut partition = Partition::new();
// add some task IDs to the pending (left) and completed (right) lists
partition.push_left(101);
partition.push_left(102);
partition.push_left(103);
partition.push_right(201);
partition.push_right(202);
// process all pending tasks and move them to completed
println!("Processing pending tasks:");
for task_id in partition.drain_to_right() {
println!("Processing task {}", task_id);
// tasks are moved to the right partition automatically
}
// all tasks are now in the completed list
assert_eq!(partition.left().len(), 0);
assert_eq!(partition.right().len(), 5);
// we can also archive completed tasks by moving to left (in a real app)
println!("Archiving old tasks:");
for task_id in partition.drain_to_left().take(2) {
println!("Archiving task {}", task_id);
// even when we only process some items, all move to the destination
}
// all tasks moved to the left (archived) partition
assert_eq!(partition.left().len(), 5);
assert_eq!(partition.right().len(), 0);§Using With Custom Types
use bose_einstein::Partition;
// a simple task type for demonstration
#[derive(Debug, Clone, Copy, PartialEq)]
struct Task {
id: u32,
is_important: bool,
}
// use partition to organize tasks by importance
let mut tasks = Partition::new();
// add some important tasks to the left partition
tasks.push_left(Task { id: 1, is_important: true });
tasks.push_left(Task { id: 2, is_important: true });
// add some regular tasks to the right partition
tasks.push_right(Task { id: 3, is_important: false });
tasks.push_right(Task { id: 4, is_important: false });
// check that we have the correct number of tasks in each partition
assert_eq!(tasks.left().len(), 2);
assert_eq!(tasks.right().len(), 2);
// we can move a task from important to regular
let moved_task = tasks.move_to_right();
assert!(moved_task.is_some());
// since we only added important tasks to the left partition,
// any task moved from left should be important
assert!(moved_task.unwrap().is_important);
// now we have one less important task
assert_eq!(tasks.left().len(), 1);
assert_eq!(tasks.right().len(), 3);
// we can access and modify tasks in each partition
// (In a real application we might use more sophisticated filtering)
let contains_task1 = tasks.left().iter().any(|task| task.id == 1) ||
tasks.right().iter().any(|task| task.id == 1);
assert!(contains_task1, "Task 1 should be in either partition");Structs§
- Drain
ToLeft - A drain iterator that moves elements from the right to the left partition.
- Drain
ToRight - A drain iterator that moves elements from the left to the right partition.
- Partition
- A data structure that partitions elements into left and right sets.