什么是 Kotlin 在 Rust 中的“reduce”操作的替代方法?

sag*_*aga 2 collections reduce functional-programming rust

我遇到了这个竞争性编程问题:

  1. nums是整数向量(长度n
  2. ops是包含+-(length n-1)的字符串向量

可以通过reduceKotlin 中的操作来解决,如下所示:

val op_iter = ops.iterator();
nums.reduce {a, b ->
    when (op_iter.next()) {
        "+" -> a+b
        "-" -> a-b
        else -> throw Exception()
    }
}
Run Code Online (Sandbox Code Playgroud)

reduce 被描述为:

从第一个元素开始累加值,并从左到右应用操作到当前累加器值和每个元素。

看起来 Rust 向量没有reduce方法。你将如何完成这项任务?

Vad*_*kan 15

编辑:自 Rust 版本 1.51.0 起,此函数称为“ reduce” 。请注意类似的函数,称为“fold”。不同之处在于,如果迭代器为空,reduce则将生成累加器,而接受累加器则将生成累加器的值,如果迭代器为空,则将生成累加器的值。Nonefold

过时的答案留下来捕捉这个函数的历史,讨论如何命名它:

reduceRust 1.48 中没有。在许多情况下,您可以使用它进行模拟,fold但请注意这些函数的语义是不同的。如果迭代器为空,fold则返回初始值,而reduce返回None。例如,如果要对所有元素执行乘法运算,则获取1空集的结果不太符合逻辑。

Rust 确实有一个fold_first与 Kotlin 相当的功能reduce,但还不稳定。主要讨论的是命名。如果您对 nightly Rust 没问题,那么使用它是一个安全的选择,因为该函数被删除的可能性很小。最坏的情况下,名字也会被改变。如果您需要稳定的 Rust,那么fold如果您对空集的不合逻辑结果感到满意,请使用。如果没有,那么您将必须实现它,或者找到一个诸如reduce之类的包。


Jmb*_*Jmb 5

科特林的reduce采取迭代器而生锈的起点的第一个项目fold,并try_fold允许您指定一个自定义的起点。

这是 Kotlin 代码的等价物:

let mut it = nums.iter().cloned();
let start = it.next().unwrap();
it.zip(ops.iter()).try_fold(start, |a, (b, op)| match op {
    '+' => Ok(a + b),
    '-' => Ok(a - b),
    _ => Err(()),
})
Run Code Online (Sandbox Code Playgroud)

操场

或者因为我们从一个可以被索引的向量开始:

nums[1..]
    .iter()
    .zip(ops.iter())
    .try_fold(nums[0], |a, (b, op)| match op {
        '+' => Ok(a + b),
        '-' => Ok(a - b),
        _ => Err(()),
    });
Run Code Online (Sandbox Code Playgroud)

操场