2010-07-30 65 views
29

我想将项目动态添加到数组中。但似乎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); 

回答

29

但似乎斯卡拉阵列&由于不可变性质,列表不提供任何动态添加项目的方法。

那么,没有。斯卡拉阵列只是Java数组,所以他们可变:

val arr = Array(1,2) 

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

但正如Java语言(C/C++/C#的/ etc。)阵列,你不能改变数组的大小

因此,您需要另一个集合,它由一个数组支持,但确实允许调整大小。 Scala中的一个合适的收集是scala.collection.mutable.ArrayBufferjava.util.ArrayList在Java等

如果你想在年底获得的List代替Array,使用scala.collection.mutable.ListBuffer代替。

+4

谢谢..“ListBuffer”是我想要的一个.. :) – RameshVel 2010-07-30 06:12:05

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) 

如果你想有一个可变的集合,可以成长和有效地处理前置,追加和插入操作,您可以使用scala.mutable.Buffer

+1

请在中间的2个例子中添加格式。 – 2010-07-30 05:56:53

+0

动态地表示“我想随时填充列表”。大小是未知的。它可能是基于传入数据的任何东西。我已更新我的问题以获得更多清晰度 – RameshVel 2010-07-30 06:01:18

3

返璞词的回答后走向:

如果你仍然想使用列表有几种方法可以在前面加上一个项目列表。你可以做的是(是的,顶部仍然是错误的):

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.也许你想让他们变得不可变的原因是速度。使用不可变数据类型处理大数据将更有效。我对吗?

+0

请注意,for(s < - strArray){outList = outList:+ s}'需要二次时间。 – 2010-07-30 05:54:49

+0

啊,臭虫!真?那outList ::: s呢?你有没有参考Scala函数的复杂性?我尝试了谷歌搜索没有发现任何东西。 从http://stackoverflow.com/questions/1241166/preferred-way-to-create-a-scala-list我认为一般的共识是预先安排和反向。 – 2010-07-30 06:01:40

+1

相同。 'List'是一个不可变的链表,因此将1个元素附加到一个元素上 - 无论您使用何种方法 - _s都需要线性时间(因为您必须复制其所有元素),所以此循环需要二次时间。追加到'ListBuffer'并调用'toList'比预先设置和反转要好,但是前置和反转比追加List更好。 – 2010-07-30 06:44:58

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做的事情。例如:

strArray map(_.toUpperCase) foreach(println) 
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) 

如果你处理列表时,要性能,更好地扭转结果,而不是最后添加新元素。在最后一个列表添加元素是nooot好:-)

+0

多数民众赞成没有要求...我想填充列表上飞“。大小是未知的。它可能是任何基于传入的数据..我已经更新了我的问题以获得更多的清晰度 – RameshVel 2010-07-30 06:08:48

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方法。

+1

您甚至不需要说'for(i < - 0到100)yield i',您可以说'(0到100)',并且如果需要的话,将其转换为与'.toList'方法等不同的集合。 – 2010-07-30 16:44:47

相关问题