微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将字符串的迭代器展平为Vec <char>甚至是FromIterator <char>

如何解决将字符串的迭代器展平为Vec <char>甚至是FromIterator <char>

正如标题所述,我有IteratorString,并且想通过合并所有Vec<char>(并同时考虑每个{{1} }(如String一样)作为Unicode标量值的序列)。 (我不需要在.chars()或类似的东西之间插入字符串,尽管我知道使用String并不会困难得多,例如other answers

itertools::intersperse

(这很好,但不是特别必要,如果我可以实现稍微更通用的类型签名:)

pub fn flatten_strings(ss: impl Iterator<Item=String>) -> Vec<char> {
    // ???
}

无论如何,这是一个简单的尝试:

pub fn flatten_strings<S>(ss: impl Iterator<Item=String>) -> S where S: FromIterator<char> {
    // ???
}

不幸的是,这不起作用,因为pub fn flatten_strings(ss: impl Iterator<Item=String>) -> Vec<char> { ss.flat_map(|s| s.chars()).collect() } 返回Chars,其中包含对它所基于的chars的引用;但是lambda拥有String的所有权,并在返回时将其删除

String

我可以通过将所有error[E0515]: cannot return value referencing function parameter `s` --> src/main.rs:2:21 | 2 | ss.flat_map(|s| s.chars()).collect() | -^^^^^^^^ | | | returns a value referencing data owned by the current function | `s` is borrowed here 收集到一个中间向量中来解决此问题,以便让某人拥有所有String,并映射String的迭代器代替&String s;但是必须分配String s的中间向量似乎效率低下,并且在一定程度上无法使用Rust的漂亮迭代器抽象:

String

类似地,我可以滚动一个循环,但这看起来也很丑。是否可以在没有其他分配的情况下有效地实现此功能,而且还可以保留Rust的迭代器抽象?

解决方法

主要问题是在任何人都可以使用依赖于它的s: String对象之前,先删除闭包中的Chars参数。

有两种解决方法。第一个比代码更冗长,但是使用相同的类型签名。第二个依赖于&str的迭代器,该迭代器使函数及其所有Chars对象失效。

pub fn flatten_strings(ss: impl Iterator<Item=String>) -> Vec<char> {
    let mut res = Vec::new();
    for s in ss {
        res.extend(s.chars());
    }
    res
}

pub fn flatten_strings2<'a>(ss: impl Iterator<Item=&'a str>) -> Vec<char> {
    ss.flat_map(|s| s.chars()).collect()
}
,

如果您可以使用临时分配,则可以在浏览列表时将每个字符串转换为Vec<char>并将其提供给flat_map。这将使更一般的情况也起作用。 您可以稍微概括一些(如Sven Marnach的建议),只返回一个impl Iterator<Item = char>而无需收集,并允许呼叫者收集它们。

use std::collections::HashSet;
use core::iter::FromIterator;
pub fn flatten_strings(ss: impl Iterator<Item=String>) -> Vec<char> {
    ss.flat_map(|s| s.chars().collect::<Vec<_>>()).collect()
}

pub fn flatten_strings2<S>(ss: impl Iterator<Item=String>)  -> S where S: FromIterator<char>  {
    ss.flat_map(|s| s.chars().collect::<Vec<_>>()).collect()
}

pub fn flatten_strings3(ss: impl Iterator<Item=String>)  -> impl Iterator<Item = char>  {
    ss.flat_map(|s| s.chars().collect::<Vec<_>>())
}

fn main() {
    let v = vec!["A string ".to_string(),"another".to_string() ];
    println!("{:?}",flatten_strings(v.clone().into_iter()));
    let h: HashSet<char> = flatten_strings2(v.clone().into_iter());
    println!("{:?}",h);
    let h: HashSet<char> = flatten_strings3(v.clone().into_iter()).collect();
    println!("{:?}",h);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。