如何获得 Rust 中最大值元素的迭代器?

问题描述 投票:0回答:4

我想访问

Vec<i32>
中最大元素旁边的元素。我正在寻找这样的东西:

let v = vec![1, 3, 2];
let it = v.iter().max_element();
assert_eq!(Some(&2), it.next());

在 C++ 中,我会使用

std::max_element
,然后只增加迭代器(有或没有边界检查,取决于我目前的冒险精神)。 Rust
max
仅返回对元素的引用,这对于我的用例来说不够好。

我想到的唯一解决方案是使用

enumerate
来获取项目的索引 - 但与 C++ 方式相比,这似乎是手动且麻烦的。

我更喜欢标准库中的东西。

这个例子是简化的 - 我实际上想附加到最高值,然后从该点循环整个容器(可能使用

cycle()
或类似的东西)。

rust iterator
4个回答
10
投票

一个简单的解决方案是使用折叠, 以下代码生成“最大数字是:99”

    let vv:Vec<i32> = (1..100).collect();
    let largest = vv.iter().fold(std::i32::MIN, |a,b| a.max(*b));
    println!("largest {} ", largest);

9
投票

C++ 迭代器与 Rust 迭代器不同。 Rust 迭代器是只向前的,并且只能遍历一次。 C++ 迭代器可以被认为是游标。有关更多详细信息,请参阅Rust 迭代器和 C++ 迭代器之间的主要区别是什么?

为了以最通用的方式实现您的目标,您必须遍历整个迭代器以找到最大值。在此过程中,每次找到新的最大值时,您都必须复制迭代器。最后可以返回最大值之后的点对应的迭代器。

trait MaxElement {
    type Iter;

    fn max_element(self) -> Self::Iter;
}

impl<I> MaxElement for I
where
    I: Iterator + Clone,
    I::Item: PartialOrd,
{
    type Iter = Self;

    fn max_element(mut self) -> Self::Iter {
        let mut max_iter = self.clone();
        let mut max_val = None;

        while let Some(val) = self.next() {
            if max_val.as_ref().map_or(true, |m| &val > m) {
                max_iter = self.clone();
                max_val = Some(val);
            }
        }

        max_iter
    }
}

fn main() {
    let v = vec![1, 3, 2];
    let mut it = v.iter().max_element();
    assert_eq!(Some(&2), it.next());
}

另请参阅:

我实际上想附加到最高值,然后从该点循环整个容器(可能使用

cycle()
或类似的东西)。

在这种情况下,我会尝试更明显:

fn index_of_max(values: &[i32]) -> Option<usize> {
    values
        .iter()
        .enumerate()
        .max_by_key(|(_idx, &val)| val)
        .map(|(idx, _val)| idx)
}

fn main() {
    let v = vec![1, 3, 2];
    let idx = index_of_max(&v).unwrap_or(0);
    let (a, b) = v.split_at(idx);
    let mut it = b.iter().chain(a).skip(1);
    assert_eq!(Some(&2), it.next());
}

另请参阅:


3
投票

如果您想要的只是最大值之后的项目的值,我会通过简单地调用

fold
来完成,跟踪迄今为止找到的最大值以及相应的下一个值:

fn main() {
    let v = vec![1, 3, 2];
    let nxt = v.iter().fold (
        (None, None),
        |acc, x| {
            match acc {
                (Some (max), _) if x > max => (Some (x), None),
                (Some (max), None) => (Some (max), Some (x)),
                (None, _) => (Some (x), None),
                _ => acc
            }
        }
    ).1;
    assert_eq!(Some(&2), nxt);
}

游乐场

根据您想要对最大值之后的项目执行的操作,类似的方法可能允许您一次性完成。


0
投票

找到

max_num
的索引,然后创建一个新的迭代器并跳过它。

fn main() {
    let nums = vec![1, 3, 2];

    let max_num = nums.iter().max().unwrap();
    let max_num_index = nums.iter().position(|num| num == max_num).unwrap();
    let max_num_it = nums.iter().skip(max_num_index);

    assert_eq!(Some(&2), max_num_it.skip(1).next());
}

在本例中,您使用的是 Vec,它可以通过索引有效地获取元素。

同时找到

max_num_index
max_num
并使用下一个索引来获取下一个元素会更快。

fn main() {
    let nums = vec![1, 3, 2];
    let (max_num_index, _max_num) = nums
        .iter()
        .enumerate()
        .max_by_key(|(_i, &num)| num)
        .unwrap();

    assert_eq!(Some(&2), nums.get(max_num_index + 1));
}
© www.soinside.com 2019 - 2024. All rights reserved.