Scala неявно преобразует map в Tuple - PullRequest
1 голос
/ 08 мая 2020

Я пытаюсь создать массив карт на основе нескольких условий. Следующее - моя функция. Хотя мне предоставлено Map scala, заставьте меня использовать tuple в качестве возвращаемого типа. Есть ли способ исправить это?

 def getSchemaMap(schema: StructType): Array[(String, String)] ={
    schema.fields.flatMap {
      case StructField(name, StringType, _, _) => Map(name-> "String")
      case StructField(name, IntegerType, _, _) => Map(name-> "int")
      case StructField(name, LongType, _, _) => Map(name-> "int")
      case StructField(name, DoubleType, _, _) => Map(name-> "int")
      case StructField(name, TimestampType, _, _) => Map(name-> "timestamp")
      case StructField(name, DateType, _, _) => Map(name-> "date")
      case StructField(name, BooleanType, _, _) => Map(name-> "boolean")
      case StructField(name, _:DecimalType, _, _) => Map(name-> "decimal")
      case StructField(name, _, _, _) => Map(name-> "String")

    }
  }

Ответы [ 3 ]

3 голосов
/ 08 мая 2020

Используйте toMap для преобразования Array[(String, String)] в Map[String, String]:

def getSchemaMap(schema: StructType): Map[String, String] = {
  schema.fields.flatMap {
    case StructField(name, StringType, _, _) => Map(name -> "String")
    case StructField(name, IntegerType, _, _) => Map(name -> "int")
    case StructField(name, LongType, _, _) => Map(name -> "int")
    case StructField(name, DoubleType, _, _) => Map(name -> "int")
    case StructField(name, TimestampType, _, _) => Map(name -> "timestamp")
    case StructField(name, DateType, _, _) => Map(name -> "date")
    case StructField(name, BooleanType, _, _) => Map(name -> "boolean")
    case StructField(name, _: DecimalType, _, _) => Map(name -> "decimal")
    case StructField(name, _, _, _) => Map(name -> "String")
  }.toMap
}

Но на самом деле вам не нужно использовать flatMap здесь, поскольку вы сопоставляете одно значение с одним значением, а не с значением к нескольким значениям. Так что в этом случае вы можете просто map значений в кортежи, а затем преобразовать список кортежей в Map

def getSchemaMap(schema: StructType): Map[String, String] = {
  schema.fields.map {
    case StructField(name, StringType, _, _) => name -> "String"
    case StructField(name, IntegerType, _, _) => name -> "int"
    case StructField(name, LongType, _, _) => name -> "int"
    case StructField(name, DoubleType, _, _) => name -> "int"
    case StructField(name, TimestampType, _, _) => name -> "timestamp"
    case StructField(name, DateType, _, _) => name -> "date"
    case StructField(name, BooleanType, _, _) => name -> "boolean"
    case StructField(name, _: DecimalType, _, _) => name -> "decimal"
    case StructField(name, _, _, _) => name -> "String"
 }.toMap
}
2 голосов
/ 08 мая 2020

Если я правильно понял, вы пытаетесь извлечь столбцы (пары имя / тип) в словарь Map[String, String]. Вы можете использовать для этого встроенные функции и использовать существующий API, поэтому я не вижу необходимости в каком-либо настраиваемом сопоставлении с шаблоном.

Вы можете использовать df.schema.fields или df.schema.toDDL, как описано ниже:

df.schema.fields.map(f => (f.name, f.dataType.typeName)).toMap // also try out f.dataType.simpleString
// res4: scala.collection.immutable.Map[String,String] = Map(col1 -> string, col2 -> integer, col3 -> string, col4 -> string)

df.schema.toDDL.split(",").map{f => (f.split(" ")(0), f.split(" ")(1))}.toMap
// res8: scala.collection.immutable.Map[String,String] = Map(`col1` -> STRING, `col2` -> INT, `col3` -> STRING, `col4` -> STRING)

И с функцией:

def schemaToMap(schema: StructType): Map[String, String] =
    schema.fields.map(f => (f.name, f.dataType.typeName)).toMap
0 голосов
/ 08 мая 2020

Все правильно, кроме flatmap, который преобразует (flatten) Array[Map(String, String)] в Array[(String, String)].

Замените flatmap на map.

def getSchemaMap(schema: StructType): Array[Map[String, String]] =
  schema.fields.map {
  //case statements
  }
...