How to sort a vector of structs by multiple columns in Rust

1 Answer

0 votes
#[derive(Debug, Clone)]
struct Item {
    a: i32,
    b: i32,
    label: String,
}

impl Item {
    fn new(a: i32, b: i32, label: &str) -> Self {
        Self {
            a,
            b,
            label: label.to_string(),
        }
    }

    fn to_string(&self) -> String {
        format!("({}, {}, {})", self.a, self.b, self.label)
    }
}

// Sort by a, then b
fn sort_data(items: &mut Vec<Item>) {
    items.sort_by(|x, y| {
        x.a.cmp(&y.a).then(x.b.cmp(&y.b))
    });
}

// Print all items
fn print_data(items: &[Item]) {
    for item in items {
        println!("{}", item.to_string());
    }
}

// Find first item by label
fn find_by_label<'a>(items: &'a [Item], label: &str) -> Option<&'a Item> {
    items.iter().find(|item| item.label == label)
}

// Filter by a
fn filter_by_a(items: &[Item], value: i32) -> Vec<Item> {
    items.iter()
        .filter(|item| item.a == value)
        .cloned()
        .collect()
}

fn main() {
    // data
    let data = vec![
        Item::new(7, 2, "python"),
        Item::new(8, 3, "c"),
        Item::new(3, 5, "c++"),
        Item::new(4, 1, "c#"),
        Item::new(3, 2, "java"),
        Item::new(7, 1, "go"),
        Item::new(1, 2, "rust"),
    ];

    // Work on a copy so original stays unchanged
    let mut items = data.clone();

    sort_data(&mut items);
    println!("Sorted data:");
    print_data(&items);

    println!("\nSearching for 'java':");
    if let Some(found) = find_by_label(&items, "java") {
        println!("{}", found.to_string());
    }

    println!("\nFiltering items where a == 7:");
    let filtered = filter_by_a(&items, 7);
    print_data(&filtered);
}



/*
run:

Sorted data:
(1, 2, rust)
(3, 2, java)
(3, 5, c++)
(4, 1, c#)
(7, 1, go)
(7, 2, python)
(8, 3, c)

Searching for 'java':
(3, 2, java)

Filtering items where a == 7:
(7, 1, go)
(7, 2, python)

*/

 



answered Jan 29 by avibootz
...