Rust中如何用迭代器链检测有序重复次数≥N的字符串字符
Absolutely! Rust's iterator adapters are perfect for cleaning up this kind of sequential grouping logic. Let's refactor your existing code to use method chains while keeping exactly the same behavior.
Original Non-Iterator Implementation
First, let's recap your working code for reference:
let v = "1122253225"; let n = 2; let mut cur_ch = '\0'; let mut repeat = 0; for ch in v.chars() { if ch == cur_ch { repeat = repeat + 1; } else { if repeat >= n { println!("There are {} repetitions of '{}'", repeat, cur_ch); } cur_ch = ch; repeat = 1; } } if repeat >= n { println!("There are {} repetitions of '{}'", repeat, cur_ch); }
Refactored Iterator-Based Implementations
Option 1: Standard Library Only (No External Dependencies)
If you want to stick to the standard library, the scan adapter is ideal here—it lets us track state (current character and repetition count) as we iterate. We just need to handle the final group separately after the iterator finishes:
let v = "1122253225"; let n = 2; // Track the last group to handle it after the main iterator let mut last_group = (None, 0); v.chars() // Use scan to carry state through each iteration .scan((None, 0), |state, ch| { let (cur_ch, repeat) = state; match cur_ch { // Same character as current group: increment count, don't emit yet Some(&c) if c == ch => { *repeat += 1; None } // New character: emit the previous group if it meets the threshold _ => { let output = if *repeat >= n { Some((*repeat, *cur_ch)) } else { None }; // Save the previous group in case we need it later last_group = (*cur_ch, *repeat); // Update state for the new character *cur_ch = Some(ch); *repeat = 1; output } } }) // Print each valid group we encounter .for_each(|(count, ch)| { println!("There are {} repetitions of '{}'", count, ch.unwrap()); }); // Don't forget to check the final group! if let (Some(ch), count) = (last_group.0, last_group.1) { if count >= n { println!("There are {} repetitions of '{}'", count, ch); } }
Option 2: Using itertools for Cleaner, More Concise Code
If you're okay with adding a popular, lightweight dependency, the itertools crate's group_by method makes this logic ridiculously clean. It abstracts away all the state-tracking for us!
First, add the dependency to your Cargo.toml:
[dependencies] itertools = "0.12"
Then the implementation becomes:
use itertools::Itertools; let v = "1122253225"; let n = 2; v.chars() // Group consecutive identical characters together .group_by(|&c| c) // Convert each group into (character, repetition count) .into_iter() .map(|(ch, group)| (ch, group.count())) // Keep only groups where repetition count is ≥ N .filter(|&(_, count)| count >= n) // Print the results .for_each(|(ch, count)| { println!("There are {} repetitions of '{}'", count, ch); });
What This Does
Both implementations produce exactly the output you specified for your example:
There are 2 repetitions of '1' There are 3 repetitions of '2' There are 2 repetitions of '2'
- The standard library version uses
scanto mimic your original loop's state tracking, but wraps it in iterator method chains for a more functional style. - The
itertoolsversion is far more readable:group_byhandles grouping consecutive characters, then we just count, filter, and print—no manual state management needed.
内容的提问来源于stack exchange,提问作者PiotrK

