我有一个包含不同变体的枚举,我希望找到匹配的第一个变体,然后通过返回变量值或将其映射到其他变换值来变换它。
在Scala中,我会使用案例类来执行以下操作:
data.collectFirst{ case d: DataD => d.data }
在Rust中,我必须两次模式匹配以获得相同的结果。有没有办法让它不那么冗长?
enum MyData {
DataA(String),
DataB(u64),
DataC(bool),
DataD { data: String, val: u32 },
}
fn main() {
// test data
let data = vec![
MyData::DataB(42),
MyData::DataD {
data: "meaning of life".to_owned(),
val: 42,
},
MyData::DataC(false),
];
// find first one that matches and map it
let found: Option<String> = data.iter()
.find(|d| match **d {
MyData::DataD { .. } => true,
_ => false,
})
.and_then(|d| match *d {
MyData::DataD { ref data, .. } => Some(data.to_owned()),
_ => None,
});
}
答案 0 :(得分:5)
您可以使用Iterator::filter_map
:
public void changeSize(final Pane pane, double width, double height) {
Duration cycleDuration = Duration.millis(500);
Timeline timeline = new Timeline(
new KeyFrame(cycleDuration,
new KeyValue(pane.maxWidthProperty(),width,Interpolator.EASE_BOTH)),
new KeyFrame(cycleDuration,
new KeyValue(pane.maxHeightProperty(),height,Interpolator.EASE_BOTH))
);
timeline.play();
timeline.setOnFinished(event->{
/* insert code here if you need */
});
}
我不太喜欢在我的迭代器链中使用大let found: Option<String> = data.iter()
.filter_map(|d| {
match *d {
MyData::DataD { ref data, .. } => Some(data.to_owned()),
_ => None,
}
})
.next();
个语句,所以我通常会在match
上创建一个方法来代替:
MyData
事实上,我的很多枚举都有这种模式:
enum MyData {
DataA(String),
DataB(u64),
DataC(bool),
DataD { data: String, val: u32 },
}
impl MyData {
fn as_data_d_data(&self) -> Option<&str> {
match *self {
MyData::DataD { ref data, .. } => Some(data),
_ => None,
}
}
}
fn main() {
let data = vec![
MyData::DataB(42),
MyData::DataD {
data: "meaning of life".to_owned(),
val: 42,
},
MyData::DataC(false),
];
let found: Option<String> = data.iter()
.filter_map(MyData::as_data_d_data)
.map(str::to_owned)
.next();
}
我甚至创建了一个自动导出这些功能的箱子。我从来没有发表它,因为我很确定类似的东西已经存在,而我却找不到它......