Skip to main content

Crate bose_einstein

Crate bose_einstein 

Source
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§

DrainToLeft
A drain iterator that moves elements from the right to the left partition.
DrainToRight
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.