給定任何切片,例如:
let words = &["one", "one", "one", "two"];
如何知道所有元素是否相同?
更進一步,如果所有元素都相同,如何回傳對第一個元素的參考?
本質上,我正在嘗試撰寫一個函式,如:
fn are_all_elements_equal<T>(elems: &[T]) -> Option<&T> {
// ... ?
}
uj5u.com熱心網友回復:
我認為這是子切片模式的一個很好的用例:
pub fn are_all_elements_equal<T: PartialEq>(elems: &[T]) -> Option<&T> {
match elems {
[head, tail @ ..] => tail.iter().all(|x| x == head).then(|| head),
[] => None,
}
}
uj5u.com熱心網友回復:
我會使用.all:https : //doc.rust-lang.org/std/iter/trait.Iterator.html#method.all
首先,如果切片為空,則回傳None。
然后在切片的其余部分上為自己抓取一個迭代器,并使用該.all函式檢查該元素是否等于您剛剛抓取的第一個元素。如果回傳 true,則回傳您的Some(first_element)
uj5u.com熱心網友回復:
作為已經發布的答案的擴展,您還可以將其設為可迭代的任何內容的通用性:
pub fn iter_all_eq<T: PartialEq>(iter: impl IntoIterator<Item = T>) -> Option<T> {
let mut iter = iter.into_iter();
let first = iter.next()?;
iter.all(|elem| elem == first).then(|| first)
}
fn main() {
println!("{:?}", iter_all_eq(&[1, 1, 1]));
println!("{:?}", iter_all_eq(&[1, 2, 1]));
println!("{:?}", iter_all_eq(&["abc", "abc", "abc", "abc"]));
}
操場
uj5u.com熱心網友回復:
一個優雅的方法是tuple_windows從itertools板條箱中使用:
use itertools::Itertools;
pub fn are_all_elements_equal<T: Eq>(elems: &[T]) -> Option<&T> {
elems.iter().tuple_windows().all(|(a, b)| a == b).then(|| &elems[0])
}
請注意,這會在空切片上發生恐慌。要處理空切片,您需要顯式回傳Noneif elems.is_empty()。
uj5u.com熱心網友回復:
使用可用的內置函式相當簡單:
fn check_all<T: Eq>(items: &[T]) -> Option<&T> {
match items.is_empty() {
true => None,
false => items.windows(2).all(|a| a[0] == a[1]).then(|| &items[0])
}
}
游樂場鏈接
.windows(2)為您提供一個包含重疊元素對的迭代器。.all(|a| a[0] == a[1])比較每個視窗的兩個元素.then(|| &items[0])Option如果前一個.all()回傳true,則回傳一個包含對第一個元素的參考,否則回傳None- 將
match items.is_empty()是必需的,因為.all()也將回傳true如果片是空的,這將導致在恐慌items[0]
應當注意,由于使用的比較.all()可能會導致相同的值進行比較本身,需要約束T到Eq,每個這樣的回答。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/311177.html
