使用不可变列表将项目附加到 for 循环中的列表?
Append items to a list in a for loop using an immutable list?
val list = List()
for(i <- 1 to 10){
list:+i
}
println(list)
这最终给了我一个空列表,尽管它应该用 1 到 10 之间的数字填充?我有一个理论,由于“:”运算符,它每次都会创建一个新列表,但我不完全确定。我已经使用 ListBuffer 解决了这个问题,但我想学习如何使用不可变列表来解决这个问题。谢谢。
您不能向不可变列表添加元素(即改变列表)。
你说得对:
I have a theory that it creates a new list each time
作为第一步考虑
var list = List.empty[Int]
for(i <- 1 to 10) {
list = list :+ i
}
println(list)
请注意,列表现在是 variable 以便我们可以重新分配值,但是 列表 仍然是一个不可变对象。事实上,对于每个迭代,我们将一个 new 列表重新分配给变量列表,并附加一个元素
如果你不喜欢使用变量你可以使用折叠操作,它与上面的for没有太大区别,它仍然构建部分列表逐个添加元素
val result = (1 to 10).foldLeft(List.empty[Int]){ (partial_list, item) =>
partial_list :+ item
}
println(result)
这里是:+
的简化签名:
def :+(elem: B): List[B]
它 returns 一个带有 elem
的新列表,因此它不会改变当前的 list
。
为了使这项工作切换到 ListBuffer
即可变的东西:
import scala.collection.mutable.ListBuffer
val buffer = ListBuffer.empty[Int]
for(i <- 1 to 10) {
buffer += i
}
println(buffer)
如果你想保留不可变列表,你可以使用 fold
:
进行累积
val list = List.empty[Int]
(1 to 10)
.foldLeft(list) { (acc, value) => acc :+ value }
这个 class 问题没有单一的功能解决方案,但这里有一些选择。
对于问题中简单的情况,可以这样做
List.range(1,11) // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
如果要根据索引为每个元素计算不同的值,请使用 tabulate
:
List.tabulate(10)(x => x*3) // List(0, 3, 6, 9, 12, 15, 18, 21, 24, 27)
(如果逻辑比这个复杂可以传一个函数)
如果您正在构建列表但不确定是否需要每个元素,请使用 Option
然后 flatten
:
def genValue(i: Int): Option[Int] = ???
List.tabulate(10)(genValue).flatten
这将丢弃 genValue
returns None
的任何值,并提取 Int
returns Some(???)
的值。
如果每个操作可能 return 不同数量的元素,使用 List
然后 flatten
:
def genValue(i: Int): List[Int] = ???
List.tabulate(10)(genValue).flatten
这将从 genValue
编辑的所有 List
值 return 中获取所有元素,并将它们放入单个 List[Int]
.
如果事先不知道 List
的长度,那么最好的解决方案可能是递归函数。虽然一开始这似乎令人生畏,但值得学习如何使用它们,因为它们通常是解决问题的最简洁方法。
val list = List()
for(i <- 1 to 10){
list:+i
}
println(list)
这最终给了我一个空列表,尽管它应该用 1 到 10 之间的数字填充?我有一个理论,由于“:”运算符,它每次都会创建一个新列表,但我不完全确定。我已经使用 ListBuffer 解决了这个问题,但我想学习如何使用不可变列表来解决这个问题。谢谢。
您不能向不可变列表添加元素(即改变列表)。 你说得对:
I have a theory that it creates a new list each time
作为第一步考虑
var list = List.empty[Int]
for(i <- 1 to 10) {
list = list :+ i
}
println(list)
请注意,列表现在是 variable 以便我们可以重新分配值,但是 列表 仍然是一个不可变对象。事实上,对于每个迭代,我们将一个 new 列表重新分配给变量列表,并附加一个元素 如果你不喜欢使用变量你可以使用折叠操作,它与上面的for没有太大区别,它仍然构建部分列表逐个添加元素
val result = (1 to 10).foldLeft(List.empty[Int]){ (partial_list, item) =>
partial_list :+ item
}
println(result)
这里是:+
的简化签名:
def :+(elem: B): List[B]
它 returns 一个带有 elem
的新列表,因此它不会改变当前的 list
。
为了使这项工作切换到 ListBuffer
即可变的东西:
import scala.collection.mutable.ListBuffer
val buffer = ListBuffer.empty[Int]
for(i <- 1 to 10) {
buffer += i
}
println(buffer)
如果你想保留不可变列表,你可以使用 fold
:
val list = List.empty[Int]
(1 to 10)
.foldLeft(list) { (acc, value) => acc :+ value }
这个 class 问题没有单一的功能解决方案,但这里有一些选择。
对于问题中简单的情况,可以这样做
List.range(1,11) // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
如果要根据索引为每个元素计算不同的值,请使用 tabulate
:
List.tabulate(10)(x => x*3) // List(0, 3, 6, 9, 12, 15, 18, 21, 24, 27)
(如果逻辑比这个复杂可以传一个函数)
如果您正在构建列表但不确定是否需要每个元素,请使用 Option
然后 flatten
:
def genValue(i: Int): Option[Int] = ???
List.tabulate(10)(genValue).flatten
这将丢弃 genValue
returns None
的任何值,并提取 Int
returns Some(???)
的值。
如果每个操作可能 return 不同数量的元素,使用 List
然后 flatten
:
def genValue(i: Int): List[Int] = ???
List.tabulate(10)(genValue).flatten
这将从 genValue
编辑的所有 List
值 return 中获取所有元素,并将它们放入单个 List[Int]
.
如果事先不知道 List
的长度,那么最好的解决方案可能是递归函数。虽然一开始这似乎令人生畏,但值得学习如何使用它们,因为它们通常是解决问题的最简洁方法。