You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中实现take_n_saving,保留指定数量非空行及中间空行

Rust实现提取指定数量非空行并保留中间空行

针对你的需求,我们可以通过两种方式实现:一种是用fold快速处理,另一种是自定义迭代器适配器实现你想要的take_n_saving链式调用风格。

方法一:使用fold直接处理

这种方式无需额外定义结构体,适合快速实现需求:

let lines = vec![
    "import a\n",
    "\n",
    "\n",
    "b = 1 + 2\n",
    "\n",
    "print(b)\n",
    "print(b + 1)\n",
    "\n",
];

// 用fold迭代收集,同时跟踪非空行的数量
let (result, _) = lines.into_iter().fold(
    (Vec::new(), 0),
    |(mut acc, count), line| {
        // 已经收集够3个非空行,直接返回当前结果
        if count >= 3 {
            return (acc, count);
        }
        acc.push(line);
        // 如果当前行不是空行,计数加1
        let new_count = if line != "\n" { count + 1 } else { count };
        (acc, new_count)
    },
);

// 此时result就是你想要的结果

方法二:自定义迭代器适配器实现take_n_saving

如果你希望用链式调用的方式实现类似take_n_saving的功能,可以自定义一个迭代器扩展:

首先定义迭代器结构体和扩展 trait:

struct TakeNSaving<I, F> {
    iter: I,
    predicate: F,
    target_count: usize,
    current_count: usize,
}

// 实现Iterator trait
impl<I, F, T> Iterator for TakeNSaving<I, F>
where
    I: Iterator<Item = T>,
    F: Fn(&T) -> bool,
    T: Clone,
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        // 已收集够目标数量,停止迭代
        if self.current_count >= self.target_count {
            return None;
        }
        self.iter.next().map(|item| {
            // 如果当前行不满足谓词(即不是空行),计数加1
            if !(self.predicate)(&item) {
                self.current_count += 1;
            }
            item
        })
    }
}

// 定义扩展trait,让所有迭代器都能调用take_n_saving
trait TakeNSavingExt: Iterator {
    fn take_n_saving<F>(self, target_count: usize, predicate: F) -> TakeNSaving<Self, F>
    where
        Self: Sized,
        F: Fn(&Self::Item) -> bool,
    {
        TakeNSaving {
            iter: self,
            predicate,
            target_count,
            current_count: 0,
        }
    }
}

// 为所有Iterator实现这个扩展
impl<I: Iterator> TakeNSavingExt for I {}

然后就可以像你期望的那样链式调用了:

let lines = vec![
    "import a\n",
    "\n",
    "\n",
    "b = 1 + 2\n",
    "\n",
    "print(b)\n",
    "print(b + 1)\n",
    "\n",
];

let result: Vec<_> = lines.into_iter()
    .take_n_saving(3, |line| line == "\n")
    .collect();

// result即为预期的向量

说明

  • take_n_saving的第一个参数是需要提取的目标行数量(这里是3),第二个参数是不需要计数但需要保留的行的判断谓词(这里是判断是否为"\n")。
  • 迭代过程中,会一直收集行,直到收集够指定数量的非谓词匹配行,之后停止迭代,完美保留中间的空行。

内容的提问来源于stack exchange,提问作者Max Smirnov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 09:57:18