如何按照2个或多个字段对结构体的Vec进行排序?

10

例子

struct MyStruct{
    row: u8,
    column: u8
}

let my_vector = a Vec<MyStruct> with like 100 items in it

假设我有一个像 ^ 这样简单的设置。我想按行排序 my_vector 列表,然后再按列排序,这样我就可以得到看起来像 sample 1 而不是 sample 2 的向量,其中包含100个项目。
my_vector = vec![
MyStruct { row: 10, column: 1 },
MyStruct { row: 10, column: 2 },
MyStruct { row: 10, column: 3 }, ]

样本 2

my_vector = vec![
MyStruct { row: 10, column: 3 },
MyStruct { row: 10, column: 1 },
MyStruct { row: 10, column: 2 }, ]

目前我一直在使用这篇文章中介绍的sort_by_key()函数按单个键进行排序,但我遇到的问题是我只能按单个键排序,而不能按两个或多个键排序。这会导致类似样例2的问题,其中我的行被排序了,但是我的列却是随机排序的。

我希望我的行和列都按顺序排列。该怎么做?谢谢


2
尝试使用sort_by函数来使用自定义谓词。my_vector.sort_by(|a, b| ...) - Chris
5个回答

21

因为 Rust 中的元组通过词典比较来实现 PartialOrd,所以您可以使用 sort_by_key() 方法:

my_vector.sort_unstable_by_key(|item| (item.row, item.column));

Playground.


5

你也可以为MyStruct实现PartialOrd或Ord <std::CMP模块>。

use core::cmp::Ordering;

#[derive(Debug, Eq, PartialEq, Ord)]
struct MyStruct {
    row: u8,
    column: u8,
}

impl PartialOrd for MyStruct {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.row == other.row {
            return Some(self.column.cmp(&other.column));
        }
        Some(self.row.cmp(&other.row))
    }
}

fn main() {
    let mut my_vector = vec![
        MyStruct { row: 10, column: 3 },
        MyStruct { row: 10, column: 1 },
        MyStruct { row: 10, column: 2 },
    ];
    my_vector.sort();
    println!("{:?}", my_vector);
}

游乐场


5

通过整理前两个解决方案的信息,并借助 GitHub Copilot 的帮助,这里提供了一种实现 按两个键排序 的工作方法:

对于可变向量,使用 sort_by 方法上的 compare 参数:

my_vector.sort_by(| a, b | if a.row == b.row {
  a.column.partial_cmp(&b.column).unwrap()
} else {
  a.row.partial_cmp(&b.row).unwrap()
});

并使用:

println!("{:#?}", locations);

将输出:

let mut locations = vec![
  Location {
    row: 1,
    column: 1
  },
  Location {
    row: 1,
    column: 2
  },
  Location {
    row: 2,
    column: 1
  },
  Location {
    row: 2,
    column: 2
  }
];

2

我认为使用match是更好的选择,因为它只比较每一对一次。使用sort_unstable_by可能会更好一些,因为不稳定排序更快,并且可以使任何比较反转(降序)-- 只需在cmp()调用中交换ab即可。

struct MyStruct {
    row: u8,
    column: u8
}

fn sort(items: &mut [MyStruct]) {
    items.sort_unstable_by(|a, b| {
        match a.row.cmp(&b.row) {
            Ordering::Equal => { a.column.cmp(&b.column) }
            v => { v }
        }
    });
}

这只是手动实现Ordering::then() - Chayim Friedman

0
你可以使用sort_by()函数。
my_vector.sort_by(|a, b| ...); 

通过使用a和b,您可以创建条件以对排序返回true link


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接