【问题标题】:How do I add the same integer to each element of a vector in Rust?如何将相同的整数添加到 Rust 中向量的每个元素?
【发布时间】:2019-10-11 17:05:58
【问题描述】:

在 Python 中,如果我有一个列表并想为每个元素添加 10,我会这样做:

bar = [2,4,5,6,7]
bar = [x + 10 for x in bar]

导致:[12,14,15,16,17]。如何在 Rust 中做到这一点?是做一个 for 循环并遍历每个向量元素的唯一方法吗?

【问题讨论】:

    标签: vector rust add


    【解决方案1】:

    Rust 的实现方式与 Python 非常相似:使用迭代器! Python 的列表推导大致等价于 iter::map 获取新元素,iter::collect 收集到新向量(或某种其他类型的集合)中。

    例如,如果barVec<i32>(或任何其他原始整数类型),并且您想为每个元素添加 10,请尝试

    bar = bar.into_iter().map(|x| x + 10).collect();
    

    (playground)

    或者,您可以使用

    就地改变元素
    bar.iter_mut().for_each(|x| *x += 10);
    

    (playground)

    这基本上就像一个 for 循环,但更简洁一些。这通常比第一种方法更有效,因为您不需要分配新向量(足够智能的编译器可能能够避免这种情况)。唯一的缺点是这个版本不太灵活。输出仍然需要是一个向量;你不能切换到哈希集或你有什么。您也无法保留旧向量的副本。请参阅下面的一些可能的示例。

    fn main() {
        let mut bar = vec![2, 4, 5, 6, 7];
        // Overwrite the old vector
        bar = bar.into_iter().map(|x| x + 10).collect();
        println!("new bar: {:?}", bar);
    
        let bar = vec![2, 4, 5, 6, 7];
        // Make a completely new vector
        // Note that this works only because i32 implements the Copy trait,
        // so we can make copies of the elements of bar without any problems
        // In more general situations, we may need to clone each element
        let foo: Vec<_> = bar.iter().map(|&x| x + 10).collect();
        println!("old bar: {:?} (it's still around)", bar);
        println!("new foo: {:?}", foo);
    
        use std::collections::HashSet;
        let bar = vec![2, 4, 5, 6, 7];
        // transform the data and collect it into a HashSet
        // instead of a vector
        let bar: HashSet<_> = bar.into_iter().map(|x| x + 10).collect();
        println!("new bar: {:?} (note that now bar is unordered)", bar);
    
        let mut bar = vec![2, 4, 5, 6, 7];
        // Overwrite the old vector in place
        bar.iter_mut().for_each(|x| *x += 10);
        println!("new bar: {:?}", bar);
    }
    

    (playground)

    【讨论】:

    • 谢谢,我只是没看懂部分答案。当你说“唯一的缺点是这个版本不太灵活。输出仍然需要是一个向量;你不能切换到散列集或者你有什么。”你说的不太灵活和输出是什么意思需要是向量吗?如果目标是始终使用向量,那么 hashSet 方法的优势是什么?
    • @Miguel 有时目标不是总是使用向量。或者即使您仍在使用向量,如果基础数据的类型发生变化,您将需要一个全新的向量。例如,如果stringsVec&lt;String&gt; 类型的向量,那么您将无法执行strings.for_each().map(|s| *s = s.len()),因为这会改变每个字符串的类型以及整个向量。
    【解决方案2】:

    这是基本代码,说明了如何按照问题默认的方式进行操作。它可能对像我这样的 Rust 初学者有用:

    fn increment_mut(p: &mut Vec<i32>, to_add: i32){
        for i in 0..p.len() {
            p[i] += to_add;
        }
    }
    
    fn main() {
        let mut p = vec![2, 4, 5, 6, 7];
        increment_mut(&mut p, 10);
    
        // Print the complete vector in Debug.
        println!("{:?}", p)
    }
    
    $ cargo run
    [12, 14, 15, 16, 17]
    

    使用iter_mut

    fn increment_mut2(p: &mut Vec<i32>, to_add: i32) {
        for x in p.iter_mut() {
            *x += to_add;
        }
    }
    
    fn main() {
        let mut p = vec![2, 4, 5, 6, 7];
        increment_mut2(&mut p, 10);
    
        // Print the complete vector in Debug.
        println!("{:?}", p)
    }
    
    $ cargo run
    [12, 14, 15, 16, 17]
    

    【讨论】:

    猜你喜欢
    • 2021-10-04
    • 2018-03-26
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多