Iterator适配器计算重复的字符

时间:2015-09-21 18:40:39

标签: string count char rust monads

我有一个类似" aaaabbbccccc"的字符串。我想在字符串的chars迭代器上创建一个适配器,它产生相同字符的计数。输出(count)必须是连续相同字符的数量。例如:

let s = "aaaabbbccccc"
for count in s.chars().MAGIC() {
    println!("{}", count)
}
// prints: 4, 3, 5

更新:这几乎可行:过去不考虑这封信:

let s = "aaaabbbcccccdd".to_string();
let mut tt = (s.chars().nth(0).unwrap(), 0);
for a in s.chars().filter_map(|x| {
    if x != tt.0 {
        tt.0 = x;
        let tt_temp = tt.1;
        tt.1 = 1;
        Some(tt_temp)
    } else {
        tt.1 += 1;
        None
    }
}) {
    println!("{:?}", a);
}

2 个答案:

答案 0 :(得分:3)

使用itertools' .coalesce(),你可以这样做:

// Map each char to an initial count of 1, then merge counts for identical chars
.map(|c| (c, 1)).coalesce(|(c, n), (d, m)|
    if c == d { Ok((c, n + m)) } else { Err(((c, n), (d, m))) })

答案 1 :(得分:2)

仅使用标准库:

use std::iter::Peekable;

struct SequentialCount<I>
    where I: Iterator
{
    iter: Peekable<I>,
}

impl<I> SequentialCount<I>
    where I: Iterator
{
    fn new(iter: I) -> Self {
        SequentialCount { iter: iter.peekable() }
    }
}

impl<I> Iterator for SequentialCount<I>
    where I: Iterator,
          I::Item: Eq
{
    type Item = (I::Item, usize);

    fn next(&mut self) -> Option<Self::Item> {
        // Check the next value in the inner iterator
        match self.iter.next() {
            // There is a value, so keep it
            Some(head) => {
                // We've seen one value so far
                let mut count = 1;
                // Check to see what the next value is without
                // actually advancing the inner iterator
                while self.iter.peek() == Some(&head) {
                    // It's the same value, so go ahead and consume it
                    self.iter.next();
                    count += 1;
                }
                // The next element doesn't match the current value 
                // complete this iteration 
                Some((head, count))
            }
            // The inner iterator is complete, so we are also complete
            None => None,
        }
    }
}

fn main() {
    let s = "aaaabbbccccc";

    for (char, count) in SequentialCount::new(s.chars()) {
        println!("{} occurs {} times", char, count)
    }
}

当然,您可以通常的工作来创建扩展特征以在迭代器上添加方法:

trait SequentialCountAdapter: Iterator {
    fn sequential_count(self) -> SequentialCount<Self>
        where Self: Sized
    {
        SequentialCount::new(self)
    }
}

impl<I> SequentialCountAdapter for I where I: Iterator {}