2017-07-04 75 views
0

我對Scala和Spark相當陌生。我創建了一個「屬性」類。每個類對象都有一個名稱,一個數據類型和一個布爾值(可爲空或不可空)。所有對象都被保存到一個ListBuffer。將StructFields添加到現有模式

我嘗試從列表中創建一個模式並將每個值傳遞給StructField()。開始工作,但不幸的是沒有更多的項目被添加到模式。

def create_schema_from_attr_list(attr_list: ListBuffer[Attribute]): StructType = { 

    // Get first list item and initiate schema 
    var schema = StructType(StructField(attr_list(0).name, attr_list(0).data_type, attr_list(0).nullable) :: Nil) 

     // Add remaining items 
     for (i <- 1 until attr_list.length) { 
      schema.add(attr_list(i).name, attr_list(i).data_type, attr_list(i).nullable) 
      println("Test " + attr_list(i).name.toString()) 
     }   
     return schema 
     } 

回答

4

add方法不會修改到位schema。認爲它有點像Java中的字符串連接方法。

您可以通過自身的加法的結果簡單地重新分配到schema使你的代碼的行爲,只要你想:

def create_schema_from_attr_list(attr_list: ListBuffer[Attribute]): StructType = { 

    // Get first list item and initiate schema 
    var schema = StructType(StructField(attr_list(0).name, attr_list(0).data_type, attr_list(0).nullable) :: Nil) 

    // Add remaining items 
    for (i <- 1 until attr_list.length) { 
    schema = schema.add(attr_list(i).name, attr_list(i).data_type, _list(i).nullable) // here 
    println("Test " + attr_list(i).name.toString()) 
    }   
    return schema 

} 

另一種解決方案,可能更簡單,是剛剛處理ListBuffer內的項目做出StructField,並將結果直接傳遞給構造函數StructType(它接受ListBuffer的父類Seq作爲參數)。

def attributeToStructField(attr: Attribute): StructField = 
    StructField(attr.name, attr.data_type, attr.nullable) 

def attributesToSchema(attrs: ListBuffer[Attribute]): StructType = 
    StructType(attrs.map(attributeToStructField)) 

如果你不熟悉的map功能:它在所有集合定義,需要一個功能A => B其變成一個ListBuffer[A]ListBuffer[B](或任何其他集合,對於這個問題)。在Scala和Spark中你會遇到這種高階函數所有其他地方。

+1

非常感謝!兩行代碼,令人印象深刻! –

2

您發起了schema,但您從未將循環中的structfield添加回schema。這就是爲什麼你添加的structFields沒有反映在發起的schema。您可以使用DataTypes API靈活創建schema。以下是我的建議。希望它有幫助

def create_schema_from_attr_list(attr_list: ListBuffer[Attribute]): StructType = { 
    // create bufferedlist of structfield 
    val bufferFields : util.ArrayList[StructField] = new util.ArrayList[StructField] 
    // Add structfields 
    for (i <- 0 until attr_list.length) { 
    bufferFields.add(DataTypes.createStructField(attr_list(i).name, attr_list(i).data_type, attr_list(i).nullable)) 
    } 
    DataTypes.createStructType(bufferFields) 
}