sorting - 根据设置对具有多个闭包之一的向量进行排序
问题描述
我想让这段代码编译:
struct Person {
name: String,
age: u32,
}
fn main() {
let sort_by = "age";
let x = vec![
Person {
name: "Peter".to_string(),
age: 18,
},
Person {
name: "Frank".to_string(),
age: 55,
},
];
let key_func;
if sort_by == "age" {
key_func = |item: &Person| {
return &item.age;
};
} else if sort_by == "name" {
key_func = |item: &Person| {
return &item.name;
};
}
x.sort_by_key(key_func);
}
我知道为什么这不能编译,但我不知道如何解决它。我尝试了几种不同的方法,包括将闭包包装在 中Box::new()
,但我无法让它工作。
起初,我想忽略这个问题,只是将所有排序逻辑(包括条件)移动到一个闭包中,但后来我不得不添加一个反向排序选项。因为我真的想*_by_key
简单起见,所以我尝试了std::cmp::Reverse
,结果发生了:
use std::cmp::Reverse;
fn main() {
let reverse = false;
// ....
let key_func = |item: &Person| {
if reverse {
return Reverse(&item.age);
} else {
return &item.age;
}
};
x.sort_by_key(key_func);
}
同样,我明白为什么会发生错误,但我不知道如何解决它。
解决方案
正如您似乎认识到的那样,问题在于key_func
只能有一个特定类型,但是这两个闭包中的每一个都有不同的类型。
一个是实现的类型,FnMut(&Person) -> &u32
另一个是实现的类型FnMut(&Person) -> &String
。
即使它们都返回相同的类型,即使它们在语法上完全相同,它们也将是两种不同的类型。这就像尝试做的一样let num: i32 = if predicate { 0 } else { "thing" }
。您可以将它们装箱到具有相同特征的特征对象中,但是装箱FnMut
s 很棘手,因为Box<FnMut...>
它没有实现FnMut
.
还有一个更根本的问题:不能使用sort_by_key
返回引用的函数。
您可以做的一件事是使用更通用的sort_by
,其中FnMut(&T, &T) -> Ordering
有逻辑可以根据哪些字段知道要返回什么,如果您真的愿意Ordering
,也许可以通过某种枚举来指导。SortBy
另一种选择是简单地sort_by_key
在分支内部调用,以便从中Vec
排序出来,或者如果您想推迟排序,则再次维护某种指标,例如SortBy
枚举,然后使用它来具体执行排序当你真正需要做的时候。
推荐阅读
- spring - 将弹簧迁移到弹簧引导控制器不起作用
- javascript - 为什么所有 redux reducer 函数都在运行时执行?
- python - Keras 中的回调异常 - Tensorflow 2.0 - Python
- c# - 使用 linq 获取具有特定对象属性的列表的一部分
- java - 如何将数据保存到房间?
- firebase - 使用 firestore 文档快照侦听器进行本地打印
- swift - Swift IOS Chart - 堆积条形图
- php - nginx 没有打开 index.php
- ios - 目标 c - 尝试在队列中复制 NSArray 时获取 exc_bad_access
- javascript - 如何在我的数组中使用 javascript 中的 foreach?