我正在尝试制作一个可以接受任何接受[]运算符的类的函数。我希望它能够接受:

  • 通过引用或值
  • 数组
  • 矢量或可索引的其他容器

  • 通过一些实验,我发现我还需要其他一些特性,例如PartialOrdPartialEq。我还需要找出容器中有多少个对象。

    这是我的代码:
    use std::ops::Index;
    use std::iter::ExactSizeIterator;
    use std::cmp::PartialEq;
    
    pub fn find<'a, I>(input: I, key: <I as std::ops::Index<u32>>::Output) -> Option<u32>
    where
        I: Index<u32> + ExactSizeIterator,
        <I as std::ops::Index<u32>>::Output: PartialEq + std::marker::Sized + std::cmp::PartialOrd,
    {
        if input.len() == 0 {
            return None;
        }
        if key < input[0] || key > input[(input.len() - 1) as u32] {
            return None;
        }
        let mut index: u32 = (input.len() - 1) as u32;
        loop {
            if key < input[index] {
                index /= 2;
                continue;
            } else if input[index] < key && input[index + 1] > key {
                return None;
            } else if key > input[index] {
                index += index / 2;
                continue;
            } else if input[index] == key {
                return Some(index);
            } else {
                return None;
            }
        }
    }
    
    fn main() {
        assert_eq!(find(&[1, 2], 2), Some(1));
        assert_eq!(find([1, 2], 2), Some(1));
        assert_eq!(find(vec![1, 2], 2), Some(1));
    }
    

    它产生以下错误:

    error[E0277]: the trait bound `&[{integer}; 2]: std::ops::Index<u32>` is not satisfied
      --> src/main.rs:36:16
       |
    36 |     assert_eq!(find(&[1, 2], 2), Some(1));
       |                ^^^^ the type `&[{integer}; 2]` cannot be indexed by `u32`
       |
       = help: the trait `std::ops::Index<u32>` is not implemented for `&[{integer}; 2]`
       = note: required by `find`
    
    error[E0277]: the trait bound `&[{integer}; 2]: std::iter::ExactSizeIterator` is not satisfied
      --> src/main.rs:36:16
       |
    36 |     assert_eq!(find(&[1, 2], 2), Some(1));
       |                ^^^^ the trait `std::iter::ExactSizeIterator` is not implemented for `&[{integer}; 2]`
       |
       = note: required by `find`
    
    error[E0277]: the trait bound `[{integer}; 2]: std::ops::Index<u32>` is not satisfied
      --> src/main.rs:37:16
       |
    37 |     assert_eq!(find([1, 2], 2), Some(1));
       |                ^^^^ the type `[{integer}; 2]` cannot be indexed by `u32`
       |
       = help: the trait `std::ops::Index<u32>` is not implemented for `[{integer}; 2]`
       = note: required by `find`
    
    error[E0277]: the trait bound `[{integer}; 2]: std::iter::ExactSizeIterator` is not satisfied
      --> src/main.rs:37:16
       |
    37 |     assert_eq!(find([1, 2], 2), Some(1));
       |                ^^^^ the trait `std::iter::ExactSizeIterator` is not implemented for `[{integer}; 2]`
       |
       = note: required by `find`
    
    error[E0277]: the trait bound `std::vec::Vec<{integer}>: std::ops::Index<u32>` is not satisfied
      --> src/main.rs:38:16
       |
    38 |     assert_eq!(find(vec![1, 2], 2), Some(1));
       |                ^^^^ the type `std::vec::Vec<{integer}>` cannot be indexed by `u32`
       |
       = help: the trait `std::ops::Index<u32>` is not implemented for `std::vec::Vec<{integer}>`
       = note: required by `find`
    
    error[E0277]: the trait bound `std::vec::Vec<{integer}>: std::iter::ExactSizeIterator` is not satisfied
      --> src/main.rs:38:16
       |
    38 |     assert_eq!(find(vec![1, 2], 2), Some(1));
       |                ^^^^ the trait `std::iter::ExactSizeIterator` is not implemented for `std::vec::Vec<{integer}>`
       |
       = note: required by `find`
    

    最佳答案

    我找到了一种实现它的方法,但是有一些限制。

    pub struct Validator {
        data: Vec<i32>,
    }
    impl<'a> From<&'a [i32; 2]> for Validator {
        fn from(input: &'a [i32; 2]) -> Self {
            Validator {
                data: input.iter().map(|c| *c).collect(),
            }
        }
    }
    impl From<[i32; 2]> for Validator {
        fn from(input: [i32; 2]) -> Self {
            Validator {
                data: input.iter().map(|c| *c).collect(),
            }
        }
    }
    impl From<Vec<i32>> for Validator {
        fn from(input: Vec<i32>) -> Self {
            Validator { data: input }
        }
    }
    
    pub fn find<T>(input: T, key: i32) -> Option<usize>
    where
        T: std::convert::Into<Validator>,
        Validator: std::convert::From<T>,
    {
        let input: Vec<i32> = input.into().data;
    
        if input.len() == 0 {
            return None;
        }
        if key < input[0] || key > input[(input.len() - 1)] {
            return None;
        }
        let mut index = input.len() - 1;
        loop {
            if key < input[index] {
                index /= 2;
                continue;
            } else if input[index] < key && input[index + 1] > key {
                return None;
            } else if key > input[index] {
                index += index / 2;
                continue;
            } else if input[index] == key {
                return Some(index);
            } else {
                return None;
            }
        }
    }
    
    fn main() {
        assert_eq!(find(&[1, 2], 2), Some(1));
        assert_eq!(find([1, 2], 2), Some(1));
        assert_eq!(find(vec![1, 2], 2), Some(1));
    }
    

    如果您需要一个接受3个或更多数字组成的数组的函数,则必须为每个元素数量实现它。您可以通过为验证器结构和要支持的类型实现VecDeque特性,来添加对更多结构(如Into或自定义结构)的支持。

    关于rust - 接受任何可索引数据类型作为参数的函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47911765/

    10-13 07:04