Повторно вывести тип последовательности в Scala - PullRequest
0 голосов
/ 07 мая 2020

Предположим, у нас есть последовательность Any

val seq = Seq(1,2,null)
seq: Seq[Any] = List(1, 2, null)

Теперь, если фильтровать ненулевой элемент, будет получена новая последовательность

val cleanSeq = seq.filterNot(_ == null)
cleanSeq: Seq[Any] = List(1, 2)

Теперь я хотел бы получить тот же тип, который я получил бы, если бы создал новую последовательность, например cleanSeq

val seq2 = Seq(1,2)
seq2: Seq[Int] = List(1, 2)

Могу ли я каким-то образом получить Seq[Int], начиная с cleanSeq?

ОБНОВЛЕНИЕ

Предыдущее было только фиктивным примером, и у меня могут быть другие типы, кроме Int, а также пример сложных типов: Array[Map[String, Float]].

Единственное предположение, которое я могу сделать, это то, что у меня есть последовательность, которая может содержать нули. Но другие элементы в последовательности имеют общий супертип, кроме Any. После удаления нулей я хочу найти общий супертип.

ОБНОВЛЕНИЕ

Вариант использования

Я хочу для создания искрового фрейма данных из столбцов, имеющих имя и значения. Значения хранятся в Seq. Из типа Seq я хочу получить схему для фрейма данных.

Определение столбца

  import reflect.runtime.universe._
  import org.apache.spark.sql.catalyst.ScalaReflection
  import org.apache.spark.sql.types._

  case class InternalColumn[A: TypeTag](colName: String, col: Seq[A]) {

    private def getType: DataType = ScalaReflection.schemaFor[A].dataType

    def genStructField: StructField = StructField(colName, getType)
  }

Создание фрейма данных:

 def createDF[T](data: Seq[T], sch: StructType): DataFrame = {
    val dataRow: Seq[Row] = data.map {
      case row: Row => row
      case prod: Product => Row(prod.productIterator.toSeq: _*)
      case d => Row(d)
    }
    spark.createDataFrame(sc.makeRDD(dataRow), sch)
  }

Использование

  def createFromColumns(data: Seq[InternalColumn[_]]): DataFrame = {
    def loop(schema: StructType, cols: Seq[InternalColumn[_]]): StructType = cols.toList match {
      case Nil => schema
      case h :: t => loop(schema.add(h.genStructField), t)
    }

    val sch: StructType = loop(new StructType(), data)
    createDF(data.map(_.col).transpose.map(Row.fromSeq), sch)
  }

val df = createFromColumns(List(InternalColumn("c1", List(1,2,3)), InternalColumn("c2", List("a", "b", "c"))))

scala> df.show()
+---+---+
| c1| c2|
+---+---+
|  1|  a|
|  2|  b|
|  3|  c|
+---+---+


scala> df.printSchema
root
 |-- c1: integer (nullable = true)
 |-- c2: string (nullable = true)


Это пока работает неплохо. Но можно создать фрейм данных, в котором есть столбец, содержащий нули. Если столбец с нулевым значением допускает значение NULL, например, он имеет StringType, он все еще работает.

Проблема возникает, когда у вас есть нули в столбце, который не допускает значения NULL, например:

scala> val df = createFromColumns(List(InternalColumn("c1", List(1,2,null)), InternalColumn("c2", List("a", "b", "c"))))
java.lang.UnsupportedOperationException: Schema for type Any is not supported

Это причина, по которой я хочу вывести тип последовательности, когда я удалил все нули.

1 Ответ

5 голосов
/ 07 мая 2020

В первую очередь вам следует постараться не потерять правильный тип (Seq[Any] - плохой запах кода, как и null), но чтобы вернуть реальный тип, вы можете выполнить проверку типов во время выполнения:

 seq.collect{ case x: Int => x } 

Это снова будет Seq[Int], выбросив все, что не Int.

Если у вас на самом деле не было других вещей, а просто Int или null, рассмотрите возможность использования Option[Int] вместо:

val seq: Seq[Option[Int]] = Seq(Some(1), Some(2), None)
// then you can do
seq.flatten // gives you Seq[Int] 

После удаления нулей я хочу найти общий супертип.

Вам нужно знать (во время написания программы), каким должен быть этот общий супертип. Затем вы можете написать код, который проверяет этот тип.

Если вы не знаете, что хотите получить от этого Seq[Int], какой тип результата вы объявите? Имейте в виду, что эти общие типы c (Int в Seq[Int]) стираются во время выполнения и существуют только для stati c проверки типов во время компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...