对一个元组向量进行排序需要对第二个值进行引用吗?

16
我有一个元组的向量,其中包含整数,我想按每个元组的第二个元素对它进行排序:

我有一个包含整数元组的向量,并希望按照每个元组的第二个元素对其进行排序:

fn main() {
    let mut tuple_list2: Vec<(u16, u16)> = vec![(1, 5), (0, 17), (8, 2)];
    tuple_list2.sort_by(|a, b| a.1.cmp(b.1));
}
编译器报错是因为b.1是一个u16而不是对一个u16的引用(&u16)。我可以通过引用b.1来解决这个问题。
fn main() {
    let mut tuple_list2: Vec<(u16, u16)> = vec![(1, 5), (0, 17), (8, 2)];
    tuple_list2.sort_by(|a, b| a.1.cmp(&b.1));
}

我不明白为什么我要这样做,特别是因为我也不需要引用a.1


4
如果您查看定义了cmp的特征,可能会有所帮助:Ord::cmp(&self, other: &Self) - Aurora0001
1
如果你倾向这样做,你可以称之为“对称”的方式进行调用:Ord::cmp(&a.1, &b.1) - bluss
1个回答

33

正如Aurora0001在评论中指出的那样,我们应该看一下cmp()函数签名:

fn cmp(&self, other: &Self) -> Ordering

我们可以看到这两个值都是通过引用传递的,因此你需要传递&b.1而不是b.1给方法,这应该不会让人感到惊讶。
尤其因为我也不需要引用a.1
这是更有趣的问题 ;-)
简单的解决方案是,点(.)运算符执行自动解引用和自动借用。让我们来看看它的效果:
struct Foo;

impl Foo {
    fn takes_value(self) {}
    fn takes_ref(&self) {}
    fn takes_mut_ref(&mut self) {}
}

fn main() {
    let mut a = Foo;

    // all of those work thanks to auto-borrowing
    a.takes_ref();
    a.takes_mut_ref();
    a.takes_value();

    // --------
    let b = Foo;
    let c = &mut b;

    // these work as well
    c.takes_ref();
    c.takes_mut_ref();

    // this one works, *if* the type implements `Copy`
    c.takes_value();
}

因此,.运算符可以帮助程序员始终传递正确类型的self参数。


注意:你正在进行的排序方式非常常见。有一种方法更适合这个任务:[T]::sort_by_key()。它看起来像这样:

// note: type annotations not required
let mut tuple_list2 = vec![(1, 5), (0, 17), (8, 2)];
tuple_list2.sort_by_key(|k| k.1);

很棒的答案。尽管Aurora0001的评论确实有帮助,但我真正需要理解的是点运算符的细节。谢谢。 - GeckStar

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