【问题标题】:What is an alternative to Kotlin's `reduce` operation in Rust?Kotlin 在 Rust 中的“reduce”操作的替代方法是什么?
【发布时间】:2019-07-20 17:25:45
【问题描述】:

我遇到了这个竞争激烈的编程问题:

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

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

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

reduce 被描述为:

从第一个元素开始累加值,从左到右对当前累加器值和每个元素进行运算。

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

【问题讨论】:

  • 要清楚,虽然Vec 缺少reduce 方法,但std::iter::Iterator 上有fold(相当于reduce),您可以通过执行@987654337 从向量中获取@

标签: collections functional-programming rust reduce


【解决方案1】:

Kotlin 的 reduce 将迭代器的第一项作为起点,而 Rust 的 foldtry_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(()),
})

Playground

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

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

Playground

【讨论】:

  • 在很多情况下,您会看到这是iterator.next().map(|first| iterator.fold(first, ...))。这样,您就可以避免来自unwrap 的恐慌并获得Option 作为最终结果。
【解决方案2】:

编辑:从 Rust 1.51.0 版本开始,这个函数被称为reduce 请注意称为fold 的类似功能。不同之处在于,reduce 如果迭代器为空,则生成 None,而 fold 接受累加器,如果迭代器为空,则生成累加器的值。

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

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

Rust 确实有一个 fold_first 函数,它相当于 Kotlin 的 reduce,但它还不稳定。 main discussion 是关于命名它。如果你对 nightly Rust 没问题,那么使用它是一个安全的选择,因为该功能被删除的可能性很小。在最坏的情况下,名称将被更改。如果您需要稳定的 Rust,那么如果您对空集的结果不合逻辑,请使用 fold。如果没有,那么您将不得不实现它,或者找到一个诸如 reduce 之类的 crate。

【讨论】:

    猜你喜欢
    • 2022-12-29
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 2015-01-04
    • 1970-01-01
    相关资源
    最近更新 更多