2010-07-30 66 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

相關問題