代码之家  ›  专栏  ›  技术社区  ›  Harry

用于Vec的DoubleEndedIterator

  •  1
  • Harry  · 技术社区  · 4 月前

    如何检查给定的列表/范围是否是另一个范围/列表的后缀。我试图使用 DoubleEndedIterator 提供向后迭代便利的特性。但是 Vec Rust标准库中的集合未实现 DoubleEndedIterator 特质。

    use std::iter::Peekable;
    
    pub fn ends_with<'a, 'b, FirstList, FirstItemType, SecondList, SecondItemType, BinaryPredicate>(
        first_list: FirstList,
        second_list: SecondList,
        binary_predicate: BinaryPredicate) -> bool
    where
        FirstList: IntoIterator<Item = &'a FirstItemType>,
        FirstList: DoubleEndedIterator<Item = &'a FirstItemType>,
        FirstItemType: 'a,
        SecondList: IntoIterator<Item = &'b SecondItemType>,
        SecondList: DoubleEndedIterator<Item = &'b SecondItemType>,
        SecondItemType: 'b,
        BinaryPredicate: Fn(&FirstItemType, &SecondItemType) -> bool
    {
        let mut f_itr = first_list.rev().into_iter().peekable();
        let mut s_itr = second_list.rev().into_iter().peekable();
    
        while let (Some(f), Some(s)) = (f_itr.peek(), s_itr.peek()) {
            if !binary_predicate(*f, *s) {
                return false;
            }
            let _ = f_itr.next();
            let _ = s_itr.next();
        }
    
        f_itr.peek().is_some() || s_itr.peek().is_none()
    }
    
    fn main() {
        let first_list = vec![1, 2, 3, 4, 5, 6];
        let second_list = vec![4, 5, 6];
    
        let res = ends_with(&first_list, &second_list, |first_item, second_item| {
            *first_item == *second_item
        });
    
        assert!(res);
    }
    

    错误

    error[E0277]: the trait bound `&Vec<{integer}>: DoubleEndedIterator` is not satisfied
      --> src/main.rs:34:29
       |
    34 |     let mut res = ends_with(&first_list, &second_list, |first_item, second_item| {
       |                   --------- ^^^^^^^^^^^ the trait `DoubleEndedIterator` is not implemented for `&Vec<{integer}>`
       |                   |
       |                   required by a bound introduced by this call
       |
    note: required by a bound in `ends_with`
      --> src/main.rs:9:16
       |
    3  | pub fn ends_with<'a, 'b, FirstList, FirstItemType, SecondList, SecondItemType, BinaryPredicate>(
       |        --------- required by a bound in this function
    ...
    9  |     FirstList: DoubleEndedIterator<Item = &'a FirstItemType>,
       |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ends_with`
    
    error[E0277]: the trait bound `&Vec<{integer}>: DoubleEndedIterator` is not satisfied
      --> src/main.rs:34:42
       |
    34 |     let mut res = ends_with(&first_list, &second_list, |first_item, second_item| {
       |                   ---------              ^^^^^^^^^^^^ the trait `DoubleEndedIterator` is not implemented for `&Vec<{integer}>`
       |                   |
       |                   required by a bound introduced by this call
       |
    note: required by a bound in `ends_with`
      --> src/main.rs:12:17
       |
    3  | pub fn ends_with<'a, 'b, FirstList, FirstItemType, SecondList, SecondItemType, BinaryPredicate>(
       |        --------- required by a bound in this function
    ...
    12 |     SecondList: DoubleEndedIterator<Item = &'b SecondItemType>,
       |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ends_with`
    
    For more information about this error, try `rustc --explain E0277`.
    
    1 回复  |  直到 4 月前
        1
  •  1
  •   Francis Gagné    4 月前

    你想把 DoubleEndedIterator 绑定在迭代器类型上,而不是可迭代类型(即实现的类型 IntoIterator ). 例如,对于 FirstList ,您需要将绑定写为 FirstList::IntoIter: DoubleEndedIterator<Item = &'a FirstItemType>, . IntoIter 是在上定义的关联类型 IntoIterator 特质。

    也, first_list.rev().into_iter().peekable() 需要更改为 first_list.into_iter().rev().peekable() 因为 rev() 未由定义 IntoIterator 特质。

    pub fn ends_with<'a, 'b, FirstList, FirstItemType, SecondList, SecondItemType, BinaryPredicate>(
        first_list: FirstList,
        second_list: SecondList,
        binary_predicate: BinaryPredicate,
    ) -> bool
    where
        FirstList: IntoIterator<Item = &'a FirstItemType>,
        FirstList::IntoIter: DoubleEndedIterator<Item = &'a FirstItemType>,
        FirstItemType: 'a,
        SecondList: IntoIterator<Item = &'b SecondItemType>,
        SecondList::IntoIter: DoubleEndedIterator<Item = &'b SecondItemType>,
        SecondItemType: 'b,
        BinaryPredicate: Fn(&FirstItemType, &SecondItemType) -> bool,
    {
        let mut f_itr = first_list.into_iter().rev().peekable();
        let mut s_itr = second_list.into_iter().rev().peekable();
    
        while let (Some(f), Some(s)) = (f_itr.peek(), s_itr.peek()) {
            if !binary_predicate(*f, *s) {
                return false;
            }
            let _ = f_itr.next();
            let _ = s_itr.next();
        }
    
        f_itr.peek().is_some() || s_itr.peek().is_none()
    }
    
    fn main() {
        let first_list = vec![1, 2, 3, 4, 5, 6];
        let second_list = vec![4, 5, 6];
    
        let res = ends_with(&first_list, &second_list, |first_item, second_item| {
            *first_item == *second_item
        });
    
        assert!(res);
    }