将Map范围直接映射到数组

4
以下代码创建了一个临时向量:
0.to(15).map(f).toArray
^^^^^^^^
Sequence
^^^^^^^^^^^^^^^
    temp Vector
^^^^^^^^^^^^^^^^^^^^^^^
                  Array

以下代码创建了一个临时数组:
0.to(15).toArray.map(f)
^^^^^^^^
Sequence
^^^^^^^^^^^^^^^
     temp Array
^^^^^^^^^^^^^^^^^^^^^^^
                  Array

有没有一种方法可以将 f 映射到 Sequence 上并直接得到一个数组,而不产生临时结果?
3个回答

5
您可以使用breakOut:
val res: Array[Int] = 0.to(15).map(f)(scala.collection.breakOut)

或者

0.to(15).map[Int, Array[Int]](f)(scala.collection.breakOut)

或者使用view

0.to(15).view.map(f).to[Array]

有关视图的更多详细信息,请参见此文档


1
你能简要解释一下 breakOut 的作用吗? - fredoverflow
此外,似乎 0.to(15).map[Int, Array[Int]](f) 已经可以正常工作,无需额外添加 (scala.collection.breakOut) 参数列表。 - fredoverflow
简而言之,breakOut 是一种方法,它可以根据所需的输入和输出类型找到正确的 CanBuildFrom 实例,否则编译器可能无法正确推断。有了正确的 CanBuildFrom 实例,您可以在映射原始集合时创建新类型的集合。更多详细信息请参见 https://dev59.com/OXI-5IYBdhLWcg3wta1q。 - Ziyang Liu
在Scala 2.12.3中,0.to(15).map[Int, Array[Int]](_ + 1)对我不起作用,因为编译器抱怨找不到CanBuildFrom - Ziyang Liu
在我的情况下,f 是一个具体的函数,因此编译器已经知道了类型。它能够与 (_ + 1: Int => Int) 或类似的东西一起工作吗? - fredoverflow
显示剩余2条评论

1
如果您知道如何构建初始的Range,您可以选择使用Array伴生对象创建Range,该对象可以直接将Range作为Array创建而无需转换:Array.range(start, end)。请保留HTML标签。
Array.range(0, 15) // Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)

可以将其从一个Array映射到另一个Array,如下所示:

Array.range(0, 15).map(f) // Array[Int] = Array(0, 2, 4, 6, 8, 10, 12, 14, ...)

注意:`Array.range(i, j)` 相当于 `i until j` (`i to j+1`) 而不是 `i to j`。

使用Array.tabulate可以更短且一次性完成,但可读性较差:

Array.tabulate(15)(f) // Array[Int] = Array(0, 2, 4, 6, 8, 10, 12, 14, ...)

1
(0 to 15).iterator.map(f).toArray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接