在 Rust 中多次使用同一个迭代器

2024-01-10

编者注:此代码示例来自 1.0 之前的 Rust 版本,当时实现了许多迭代器Copy。此代码的更新版本会产生不同的错误,但答案仍然包含有价值的信息。

我正在尝试编写一个函数来将字符串拆分为字母和数字块;例如,"test123test"会变成[ "test", "123", "test" ]。到目前为止,这是我的尝试:

pub fn split(input: &str) -> Vec<String> {
    let mut bits: Vec<String> = vec![];
    let mut iter = input.chars().peekable();
    loop {
        match iter.peek() {
            None => return bits,
            Some(c) => if c.is_digit() {
                bits.push(iter.take_while(|c| c.is_digit()).collect());
            } else {
                bits.push(iter.take_while(|c| !c.is_digit()).collect());
            }
        }
    }
    return bits;
}

然而,这不起作用,永远循环。似乎它正在使用的克隆iter每次我打电话take_while,一遍又一遍地从同一个位置开始。我希望它使用相同的iter每次,在所有的迭代器上推进相同的迭代器each_times。这可能吗?


正如您所确定的,每个take_while呼叫重复iter, since take_while takes selfPeekable字符迭代器是Copy http://doc.rust-lang.org/master/std/kinds/trait.Copy.html. (仅在 Rust 1.0 之前正确 - 编辑器)

您希望每次都修改迭代器,即take_while操作于&mut到你的迭代器。这正是.by_ref https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.by_ref适配器用于:

pub fn split(input: &str) -> Vec<String> {
    let mut bits: Vec<String> = vec![];
    let mut iter = input.chars().peekable();
    loop {
        match iter.peek().map(|c| *c) {
            None => return bits,
            Some(c) => if c.is_digit(10) {
                bits.push(iter.by_ref().take_while(|c| c.is_digit(10)).collect());
            } else {
                bits.push(iter.by_ref().take_while(|c| !c.is_digit(10)).collect());
            },
        }
    }
}

fn main() {
    println!("{:?}", split("123abc456def"))
}

Prints

["123", "bc", "56", "ef"]

但是,我认为这是不正确的。

我实际上建议像平常一样写这个for循环,使用char_indices https://doc.rust-lang.org/std/primitive.str.html#method.char_indices迭代器:

pub fn split(input: &str) -> Vec<String> {
    let mut bits: Vec<String> = vec![];
    if input.is_empty() {
        return bits;
    }

    let mut is_digit = input.chars().next().unwrap().is_digit(10);
    let mut start = 0;

    for (i, c) in input.char_indices() {
        let this_is_digit = c.is_digit(10);
        if is_digit != this_is_digit {
            bits.push(input[start..i].to_string());
            is_digit = this_is_digit;
            start = i;
        }
    }

    bits.push(input[start..].to_string());
    bits
}

这种形式还允许用更少的分配来做到这一点(即,Strings 不是必需的),因为每个返回值只是input,我们可以用生命周期来说明这一点:

pub fn split<'a>(input: &'a str) -> Vec<&'a str> {
    let mut bits = vec![];
    if input.is_empty() {
        return bits;
    }

    let mut is_digit = input.chars().next().unwrap().is_digit(10);
    let mut start = 0;

    for (i, c) in input.char_indices() {
        let this_is_digit = c.is_digit(10);
        if is_digit != this_is_digit {
            bits.push(&input[start..i]);
            is_digit = this_is_digit;
            start = i;
        }
    }

    bits.push(&input[start..]);
    bits
}

所有改变的是类型签名,删除了Vec<String>类型提示和.to_string calls.

人们甚至可以编写这样的迭代器,以避免分配Vec。就像是fn split<'a>(input: &'a str) -> Splits<'a> { /* construct a Splits */ } where Splits是一个实现的结构体Iterator<&'a str>.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Rust 中多次使用同一个迭代器 的相关文章

随机推荐

  • PIMPL 习惯用法真的在实践中使用吗?

    我正在看书 卓越的 C Herb Sutter 所著 在那本书中我了解了 PIMPL 习惯用法 基本上 这个想法是创建一个结构private的对象class并将它们动态分配给减少编译时间 并且还以更好的方式隐藏私有实现 例如 class X
  • 如何防止 json_encode() 删除含有无效字符的字符串

    有没有办法保留json encode 从返回null对于包含无效 非 UTF 8 字符的字符串 在复杂的系统中进行调试可能会很痛苦 实际看到无效字符或者至少将其省略会更合适 就目前情况而言 json encode 会默默地丢弃整个字符串 示
  • Ionic 2:Cordova 不可用。确保包含 cordova.js 或在设备/模拟器中运行(在模拟器中运行)

    我刚刚设置了我的第一个 ionic 2 应用程序 我相当广泛地使用了 ionic 1 我正在尝试使用离子原生相机 http ionicframework com docs v2 native camerapreview 预览插件 设置非常简
  • 将 Maven 项目转换为 Eclipse 的动态 Web 项目

    使用 Maven 创建一个 Web 项目 mvn archetype generate DgroupId com trial DartifactId message DarchetypeArtifactId maven archetype
  • 如何接收短信并根据短信内容拨打电话提醒某人?

    因此 我尝试接收传入的短信 并根据短信的内容拨打带有特定录音的电话 例如 我有一个带调制解调器的门传感器 可以在门打开或关闭时向我的 twilio 发送文本 如果 Twilio 收到 门已打开 文本 则 twilio 将拨打我的手机并播放显
  • 如何创建所有数字组合的n维数组?

    我想创建一个函数AllCombnations d maxValue 这将创建一个包含从 0 到 的所有数字组合的 d 维数组maxValue 例如 在 3D 空间中创建所有数字组合 从 0 到maxValue可能是这样的 for int i
  • 挽救模块内特定类型的所有错误

    我有一个模块 在其中执行项目的所有加密 解密任务 我想抓住任何OpenSSL Cipher CipherError该模块中发生的异常以便我可以处理它们 是否可以做类似的事情 rescue from OpenSSL Cipher Cipher
  • Symfony 4 Composer 脚本

    我刚刚安装了 Symfony 4 项目并在中找到了此部分composer json scripts auto scripts cache clear symfony cmd assets install PUBLIC DIR symfony
  • 如何获得没有标签的地图?

    我想要一张有路网的地图 我只需要一张图片 但没有标签 地图上的文字 我尝试从 Google API 获取这样的地图并想 element geometry works 但是 例如 依然充满文字 如何获取没有文字标签的路网图 静态图片也可以 任
  • 如何打开两个Javafx窗口?

    我正在使用 javafx 想在按钮的 setOnAction 中编写代码来关闭 javafx1 类并运行 javafx2 类 但我看到错误 应用程序启动不得被调用多次 我怎样才能解决这个问题 This code is in the clas
  • 这段 JavaScript 代码是什么意思?

    var myval function 我不明白 function 含义甚至其他代码 你所拥有的是 自调用匿名函数 您首先通过在函数本身周围添加括号来创建函数表达式 只是为了写 function 在这种情况下不起作用 因为这将定义一个函数声明
  • Magento 扩展 404 错误

    我很难过 我有一个自定义扩展 可以在 Mac Leopard 本地完美运行 但是在将实时推送到主机 Centos Linux 后 当我尝试调用前端路由器时 出现 Magento 404 错误 例如这个网址 domain shop index
  • PHP 如何获取带有类和名称空间路径的方法名称作为字符串?

    我真的很讨厌写这个问题 因为我是一种 研究人员 而且 我总是能找到我正在寻找的东西 但这一个让我很烦恼 我在任何地方都找不到答案 所以 事情是这样的 正如标题所示 我需要获取一个方法名称 其中尾随类和命名空间路径作为字符串 我的意思是这样的
  • 关于android加速度计onSensorChanged的信息

    我正在尝试在android平台上编写一个体感游戏 我将整个运动检测算法包含到 onSensorChanged 函数中 问题在于该函数根据输入执行不同的时间 我对函数如何执行和调用有一些疑问 1 如果我的函数执行很长时间 并且发生了 2 个
  • 使用 Julia 中的 Images 导出图像

    假设我有一个m by n by 3的数组Uint8它表示一个图像 其中假定使用 RGB 色彩空间 我想使用以下命令将其导出为每像素 24 位 PNG 图像Images包裹 我怎样才能做到这一点 我天真地尝试申请imwrite到随机生成的原始
  • 附加 pandas 数据框自动转换为 float 但需要 int

    如何让 pandas 附加一个整数并保留整数数据类型 我意识到我可以在输入数据后将 df test astype int 添加到整个列 但如果我可以在附加数据时执行此操作 那么这似乎是一个更好的方法 这是一个示例 from bitstrin
  • 即使包含当前脚本,也要获取当前脚本的 URL?

    我有一个 PHP 脚本 需要知道它的 URL 即使它包含在另一个脚本中 我试过了 SERVER REQUEST URI 但这不会将 URI 返回到我的脚本 而是将 URI 返回到包括脚本 我也尝试过 dirname FILE 但我似乎无法将
  • 通过 gcloud 命令行工具触发特定 git 提交的构建

    我遇到的所有示例均采用以下格式 gcloud container builds submit config cloudbuild yaml 手册页内容如下 SOURCE The source directory on local disk
  • 自定义按钮的核心图形与图像

    我什么时候应该使用核心图形而不是图像来制作自定义 UIButton 核心显卡速度更快吗 除了分辨率独立之外 还有其他主要好处吗 核心显卡的优点 绘制按钮的代码可能比图像文件小 允许动态修改 轻微更改 而无需添加完整的第二个图像 正如您提到的
  • 在 Rust 中多次使用同一个迭代器

    编者注 此代码示例来自 1 0 之前的 Rust 版本 当时实现了许多迭代器Copy 此代码的更新版本会产生不同的错误 但答案仍然包含有价值的信息 我正在尝试编写一个函数来将字符串拆分为字母和数字块 例如 test123test 会变成 t