在Scala中创建动态增长数组的最佳方法是什么?

时间:2010-07-30 05:26:14

标签: scala

我想将项目动态添加到数组中。但是由于不可变的特性,Scala数组和列表似乎没有提供任何动态添加项的方法。

所以我决定使用List数据类型来使用这个 :: 方法来实现这一点。我的代码看起来像这样

var outList = List(Nil)
val strArray = Array("ram","sam","bam")

for (str<-strArray)
     outList = str :: outList

虽然它以某种方式工作,但问题是新的字符串被预先附加到列表中。但理想的要求是数据的顺序。是的,我知道你在想什么,你可以反转最终结果列表以获得原始订单。但问题是它是一个巨大的阵列。我相信它不是一个解决方案,虽然它解决了这个问题。我相信应该有一个简单的方法来解决这个问题......

我破解Scala的原因是学习编码的功能方式。拥有 var (可变类型)并在运行中填充列表似乎不是解决问题的功能方法。

我该怎么做?

理想情况下,我希望在Scala中实现类似的功能(在C#代码下面)

List<int> ls = new List<int>();    
for (int i = 0; i < 100; i++)
    ls.Add(i);

7 个答案:

答案 0 :(得分:32)

  

但似乎Scala Arrays&amp;由于不可变性,列表不提供任何动态添加项的方法。

嗯,不。 Scala Arrays只是Java数组,因此它们 可变:

val arr = Array(1,2)

arr(0) = 3 // arr == Array(3, 2)

但就像Java(和C / C ++ / C#/ etc。)数组一样,你不能改变数组的大小

所以你需要另一个由数组支持的集合,但允许调整大小。 Scala中的合适集合是scala.collection.mutable.ArrayBuffer,Java中的java.util.ArrayList等等。

如果您想在最后获得List而不是Array,请改用scala.collection.mutable.ListBuffer

答案 1 :(得分:4)

继续使用反语:

如果您仍想使用列表,可以通过几种方法将项目添加到列表中。你可以做的是(是的,最重要的部分仍然是错误的):

scala> var outList : List[String] = Nil
outList: List[String] = List()

scala> val strArray = Array("a","b","c")
strArray: Array[java.lang.String] = Array(a, b, c)

scala> for(s <- strArray)      
     | outList = outList :+ s

scala> outList
res2: List[String] = List(a, b, c)

注意:+运算符。如果您愿意附加,则使用s +:outList。

现在谁在Scala中编程并不好玩? ;)

P.S。也许你想让它们变得不可变的原因是速度。使用不可变数据类型处理大数据会更有效。我是对的吗?

答案 2 :(得分:4)

如果您想使用可变缓冲区,请提及。它看起来像这样:

scala> var outList = scala.collection.mutable.Buffer[String]()
outList: scala.collection.mutable.Buffer[String] = ArrayBuffer()

scala> for(str<-strArray) outList += str                          

scala> outList
res10: scala.collection.mutable.ListBuffer[String] = ListBuffer(ram, sam, bam)

无论如何,也许最好直接用strArray做你想做的事情。 E.g:

strArray map(_.toUpperCase) foreach(println)

答案 3 :(得分:4)

如果要使用不可变结构,可以使用++方法:

scala> val orgList = List(1,2,3)
orgList: List[Int] = List(1, 2, 3)

scala> val list2Add = List(4,5,6)
list2Add: List[Int] = List(4, 5, 6)

scala> val newList = orgList ++ list2Add
newList: List[Int] = List(1, 2, 3, 4, 5, 6)

如果你想对这些元素做更多的工作,而不仅仅是添加它们,你可以使用更高阶的函数:

val newList = orgList ++ list2Add.map(_ * 2)
newList: List[Int] = List(1, 2, 3, 8, 10, 12)

或者使用for循环:

val newList = orgList ++ {for(x <- list2Add) yield 2*x}

或者你可以创建一些递归循环:

def addAll(toList: List[Int], fromList: List[Int]): List[Int] =
  fromList match {
    case x :: tail => addAll(2*x :: toList, tail)
    case Nil => toList
  }

val newList = addAll(orgList, list2Add )

但在这种情况下,添加元素的顺序将颠倒过来:

List(12, 10, 8, 1, 2, 3)

如果在使用列表时需要性能,最好反转结果而不是尝试最后添加新元素。最后在列表中添加元素是好的: - )

答案 4 :(得分:3)

好的,有一些事情需要澄清。

这是错误的,你要制作一个包含空列表的单元素列表:

scala> var outList = List(Nil) 
outList: List[object Nil] = List(List())

Nil是空列表:

scala> var outList: List[String] = Nil
outList: List[String] = List()

或者,如果您愿意:

scala> var outList = List[String]() 
outList: List[String] = List()

如果没有更多背景信息,很难通过“动态”了解您的意思。您的示例代码最好写成:

scala> val strArray = Array("ram","sam","bam")
strArray: Array[java.lang.String] = Array(ram, sam, bam)

scala> strArray toList
res0: List[java.lang.String] = List(ram, sam, bam)

如果你想要一个可以增长并有效处理prepend,append和insert操作的可变集合,你可以使用scala.mutable.Buffer

答案 5 :(得分:2)

如果您要创建新集合,可以使用yield关键字:

val outlist = for(i <- 0 to 100) yield i

或者:

val arrList = "Some" :: "Input" :: "List" :: Nil
val outlist = for ( i <- arrList ) yield i

从技术上讲,outlist是上述两个示例中的Seq,因此如果需要List的某些方法,可能需要在其上调用toList方法。

答案 6 :(得分:0)

我们可以按照建议使用ArrayBuffer。 但是,我创建了一个简单的程序,该程序不使用int数组的任何参数,它可以让您输入数字,最后我们将它们显示出来。

from datetime import date
from dateutil.relativedelta import relativedelta

def AgeTest(dob):
age = relativedelta(date.today(), dob)
print (age)
return age.years, age.months, age.days