连接字符串向量的向量

2024-02-08

我正在尝试编写一个函数,该函数接收字符串向量的向量并返回连接在一起的所有向量,即它返回字符串向量。

到目前为止我能做的最好的事情如下:

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let vals : Vec<&String> = vecs.iter().flat_map(|x| x.into_iter()).collect();
    vals.into_iter().map(|v: &String| v.to_owned()).collect()
}

然而,我对这个结果并不满意,因为看起来我应该能够得到Vec<String>从一开始collect打电话,但不知何故我不知道该怎么做。

我更有兴趣弄清楚why正是返回类型collect is Vec<&String>。我试图从 API 文档和源代码中推断出这一点,但尽管我尽了最大努力,我什至无法理解函数的签名。

那么让我尝试追踪每个表达式的类型:

- vecs.iter(): Iter<T=Vec<String>, Item=Vec<String>>
- vecs.iter().flat_map(): FlatMap<I=Iter<Vec<String>>, U=???, F=FnMut(Vec<String>) -> U, Item=U>
- vecs.iter().flat_map().collect(): (B=??? : FromIterator<U>)
- vals was declared as Vec<&String>, therefore 
      vals == vecs.iter().flat_map().collect(): (B=Vec<&String> : FromIterator<U>). Therefore U=&String.

我假设上面的类型推断器能够弄清楚U=&String根据类型vals。但是,如果我在代码中为表达式提供显式类型,则编译不会出现错误:

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let a: Iter<Vec<String>> = vecs.iter();
    let b: FlatMap<Iter<Vec<String>>, Iter<String>, _> = a.flat_map(|x| x.into_iter());
    let c = b.collect();
    print_type_of(&c);
    let vals : Vec<&String> = c;
    vals.into_iter().map(|v: &String| v.to_owned()).collect()
}

清楚地,U=Iter<String>...请帮我清理这个烂摊子。

EDIT:感谢 bluss 的提示,我能够实现一个collect如下:

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    vecs.into_iter().flat_map(|x| x.into_iter()).collect()
}

我的理解是通过使用into_iter我转让所有权vecs to IntoIter并进一步沿着调用链,这使我能够避免复制 lambda 调用内的数据,因此 - 神奇地 - 类型系统给了我Vec<String>它曾经总是给我Vec<&String>前。虽然看到高级概念如何反映在图书馆的运作中确实非常酷,但我希望我知道这是如何实现的。

EDIT 2:经过费力的猜测过程,查看 API 文档并使用这个方法 https://stackoverflow.com/a/29168659/3646645为了破译这些类型,我对它们进行了完整注释(忽略生命周期):

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let a: Iter<Vec<String>> = vecs.iter();
    let f : &Fn(&Vec<String>) -> Iter<String> = &|x: &Vec<String>| x.into_iter();
    let b: FlatMap<Iter<Vec<String>>, Iter<String>, &Fn(&Vec<String>) -> Iter<String>> = a.flat_map(f);
    let vals : Vec<&String> = b.collect();
    vals.into_iter().map(|v: &String| v.to_owned()).collect()
}

我会想:为什么在外部 vec 上使用 iter() 而在内部 vec 上使用 into_iter() ?使用into_iter()实际上至关重要,这样我们就不必先复制内部向量,然后复制里面的字符串,我们只需获得它们的所有权即可。

我们实际上可以将其写成求和:将向量两两连接起来。由于我们总是重复使用同一累积向量的分配和内容,因此该操作是线性时间的。

为了最大限度地减少增长和重新分配向量所花费的时间,请预先计算所需的空间。

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let size = vecs.iter().fold(0, |a, b| a + b.len());
    vecs.into_iter().fold(Vec::with_capacity(size), |mut acc, v| {
        acc.extend(v); acc
    })
}

如果您确实想克隆所有内容,已经有一种方法可以实现,您只需使用vecs.concat() /* -> Vec<String> */


该方法与.flat_map很好,但如果你不想再次克隆字符串,你必须使用.into_iter()在所有级别:(x is Vec<String>).

vecs.into_iter().flat_map(|x| x.into_iter()).collect()

如果您想克隆每个字符串,您可以使用以下命令:(已更改.into_iter() to .iter() since x这里有一个&Vec<String>这两种方法实际上会产生相同的结果!)

vecs.iter().flat_map(|x| x.iter().map(Clone::clone)).collect()

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

连接字符串向量的向量 的相关文章

随机推荐

  • Windows 窗体,从父窗体获取属性

    我遇到了一点问题 我在父表单中有一个数据表 我打开一个对话框表单 获取数据表属性并创建一个复选框列表 这将用于导出这些列 但是当我运行应用程序时 parentform 属性为空 我尝试在父窗体和对话框窗体中设置它 我假设如果调用 ShowD
  • 我在哪里弄乱了输出格式?

    因此 当我尝试运行代码时收到一条错误消息 但我无法弄清楚问题到底是什么 它说这是一个 ValueError 但我不知道到底是哪一个 也许只是迟到了 但我却不知所措 这是我的代码 def sort count dict avg scores
  • 为Android应用程序设置图标

    如何为我的 Android 应用程序设置图标 如果您希望您的应用程序在多种设备上可用 您应该将应用程序图标放在不同的位置res drawable 提供的文件夹 在每个文件夹中 您应该包含一个 48dp 大小的图标 drawable ldpi
  • go helm 图表模板中的循环[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在尝试在 kubernetes helm 图表中循环计数 如下所示 reaction mongo url big mongodb for m
  • TypeScript 将camelCase 键转换为snake_case

    想象一下 我们有一些具有驼峰命名法属性的对象类型 type Foo propertyBob string propertyJane number 有没有办法创建一个将camelCase转换为snake case的泛型 例如 type foo
  • 发布操作:“提交助手应用程序时出错”,没有显示错误

    我正在尝试发布我的第一个 Google Assistant 操作 但在尝试提交应用程序时 控制台告诉我 提交助理应用程序时出错 但没有任何详细信息 是否有任何日志或其他内容可以为我提供有关在提交之前需要修复的更多详细信息 我迷路了 谢谢 许
  • Pytorch RuntimeError:CUDA 内存不足且有大量可用内存

    在训练模型时 我遇到了以下问题 RuntimeError CUDA out of memory Tried to allocate 304 00 MiB GPU 0 8 00 GiB total capacity 142 76 MiB al
  • 使用 NetBeans 6.8 进行 XSLT 自动完成

    我记得当时NetBeans 6中支持XSLT 现在我使用NetBeans 6 8 但仍然找不到这样的插件 你能帮助我吗 工具 gt 插件 gt 设置添加http updates netbeans org netbeans updates 6
  • 优化TreeView方法

    我有一个非常大的方法可以插入子元素TreeView 基本上我做了两个不同的查询 并在 I N 上设置了很小的更改 第一个 foreach 插入父级的第一个子级 第二个 foreach 插入之前创建的子级的子级 Foreach查询只是改变条件
  • Android 兼容包不包含 Activity.getFragmentManager()

    我开始尝试使用 3 月 3 日刚刚发布的 Android 兼容包向我的 Android 应用程序添加片段 该应用程序基于 2 1 我将该库包含到我的项目中 并开始将代码从基于 Activity 的类移动到基于 Fragment 的类 但我注
  • 如何在复杂的单元格中找到元素?

    我有一个复杂的元胞数组 例如 A 1 2 3 4 5 6 7 8 9 10 如何找到A中的元素 例如 我想检查 9 是否在 A 中 如果您的元胞数组可以有任意数量的嵌套级别 则只需递归所有级别即可检查值 这是一个可以执行此操作的函数 fun
  • iPhone:如何使用 Xcode 向 Web 服务发送 HTTP 请求

    如何使用 Objective C 向 Web 服务发送 HTTP 请求 我需要从 MySQL 数据库中获取一些数据 因此我需要发送请求以便获取数据 编辑 因为这是一个热门问题 而且时间在不断流逝 与此同时 Apple 引入了 NSJSONS
  • 使用第三方库和 Carthage 进行单元测试

    使用 Carthage 进行依赖管理的正确方法是什么 而且还能够用它为其引入的类型编写测试 例如 这是假设的 如果我引入 AlamoFire 并假设它有一个响应协议和不同的协议具体类型符合响应协议 在我自己的图书馆里 如果我要做的话 tes
  • 沿给定轴打乱 NumPy 数组

    给定以下 NumPy 数组 gt a array 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 洗牌单行很简单 gt shuffle a 0 gt a array 4 2 1 3 5 1 2 3 4 5 1 2 3 4 5 是
  • 如何从 Angular 中的 NgFor 循环中删除重复记录

    我正在尝试从 ngfor 循环中删除重复记录 并仅保留该记录点击次数最多的记录 目标是显示用户的点击 URL 但目前 当为同一 URL 创建新记录时 它会显示在列表中 见下图 点击操作按预期进行 但一段时间后列表将变得难以辨认 我正在尝试展
  • R:从 Quanteda DFM、稀疏文档特征矩阵、对象中删除正则表达式?

    Quanteda 包提供了稀疏文档特征矩阵 DFM 其方法包含删除功能 https rdrr io cran quanteda man removeFeatures html 我努力了dfm x removeFeatures b a z 1
  • 从内核空间到用户空间的事件通知

    当内核空间发生事件时如何通知用户空间应用程序 当数据到达某个 GPIO 时 硬件会生成中断 该数据被复制到内核缓冲区 此时 我希望驱动程序通知应用程序它可以调用read函数将数据从内核缓冲区复制到用户空间缓冲区 我想用epoll方法 但是e
  • Pygame 没有在窗口中显示任何内容[重复]

    这个问题在这里已经有答案了 刚刚开始使用 python 和 pygames 编程 每当我尝试使用 pygames 运行 py 文件时 都会出现 pygames 窗口 但其中绝对没有任何内容 日志中没有错误 但没有任何显示 只是灰屏 我尝试在
  • mysql - 基于其他行更新行

    我希望根据其他行的特定条件更新某些行 假设表格如下所示 COLUMNS time type genre doubles triples ROW 1 2010 06 21 12 00 1 1 0 0 ROW 2 2010 06 21 12 0
  • 连接字符串向量的向量

    我正在尝试编写一个函数 该函数接收字符串向量的向量并返回连接在一起的所有向量 即它返回字符串向量 到目前为止我能做的最好的事情如下 fn concat vecs vecs Vec