【问题标题】:Function that accepts any indexable data type as an argument接受任何可索引数据类型作为参数的函数
【发布时间】:2018-06-03 08:26:49
【问题描述】:

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

  1. 按引用或按值的数组

  2. 向量或任何其他可索引的容器

通过一些实验,我发现我还需要一些其他特征,例如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`

【问题讨论】:

  • 它没有编译错误,但尝试使用上面显示的示例运行它。尝试使用 [6,7,8,3] 或 &[1,2,3,4,8] 参数调用它
  • 请寻求写一个正确的minimal reproducible example。重现Rust Playground 中的确切问题是一个加分项。
  • 阅读错误文本并告诉我们为什么您认为编译器在错误中不正确也是一个好主意。例如,如果它告诉您某些事情没有实现,您为什么认为它是?否则,您似乎故意忽略错误消息。
  • 切片是否足够?如果是 → play.rust-lang.org/… 可能就是你所需要的。

标签: rust traits iterator-traits


【解决方案1】:

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

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 个或更多数字的数组的函数,则必须为每个元素数量实现它。您可以通过为验证器结构和您想要支持的类型实现 Into 特征来添加对更多结构(如 VecDeque 或自定义结构)的支持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    相关资源
    最近更新 更多