【问题标题】:How to compare two StructType sharing same contents?如何比较两个共享相同内容的 StructType?
【发布时间】:2018-07-19 17:36:10
【问题描述】:

似乎StructType 保留了顺序,因此包含相同StructFields 的两个StructType 不被视为等效。

例如:

val st1 = StructType(
StructField("ii",StringType,true) :: 
StructField("i",StringType,true) :: Nil)

val st2 = StructType(
StructField("i",StringType,true) :: 
StructField("ii",StringType,true) :: Nil)

println(st1 == st2)

返回 false,即使它们都有 StructField("i",StringType,true)StructField("ii",StringType,true),只是顺序不同。

我需要一个可以说这两个是等价的测试,因为就我的目的而言,这两个没有什么不同。

val schema1 = StructType(StructField("A",ArrayType(st1,true),true) :: Nil)

val schema2 = StructType(StructField("A",ArrayType(st2,true),true) :: Nil)

val final_schema = StructType((schema1 ++ schema2).distinct)

final_schmea 的结果应该只有一个 StructTypeA 而不是两个,但 distinct 认为这两个 StructType 不同,所以我最终得到两个不同的 StructField,名为 @987654336 @。所以我的问题是,有没有办法根据它们的内容而不是订单来比较两个StructTypes?

编辑:

经过进一步调查,由于StructType基本上是Seq<StructField>,我可以做content comparison for that works for Seq,但我正在想一种方法可以最有效地对嵌入式StructType进行比较。

【问题讨论】:

    标签: scala apache-spark apache-spark-sql


    【解决方案1】:

    我比较架构如下:

    assert(structType1 == structType2, "not equal schemas")
    

    即使在 Spark 的代码中,他们也使用 ' == ' 比较 StructTypes

    您可以在 org.apache.spark.sql.sources

    下查看 TableScanSuite.scala

    https://github.com/apache/spark/blob/8b7d4f842fdc90b8d1c37080bdd9b5e1d070f5c0/sql/core/src/test/scala/org/apache/spark/sql/sources/TableScanSuite.scala#L249

    assert(expectedSchema == spark.table("tableWithSchema").schema)
    

    希望对你有帮助

    【讨论】:

      【解决方案2】:

      这可能可以清理,但它可以工作并处理嵌套的 StructType:

      def isEqual(struct1: StructType, struct2: StructType): Boolean = {
        struct1.headOption match {
          case Some(field) => {
            if(field.dataType.typeName != "struct") {
              struct2.find(_ == field) match {
               case Some(matchedField) => isEqual(StructType(struct1.filterNot(_ == field)), StructType(struct2.filterNot(_ == field)))
               case None => false
              }
            } else {
              val isEqualContents = struct2.find(x => x.name == field.name && x.nullable == field.nullable && x.dataType.typeName == "struct") match {
                case Some(matchedField) => isEqual(field.dataType.asInstanceOf[StructType], matchedField.dataType.asInstanceOf[StructType])
                case None => false
              }
              if(isEqualContents) isEqual(StructType(struct1.filterNot(_ == field)), StructType(struct2.filterNot(_ == field))) else false
            }
          }
          case None => struct2.size == 0
        }
      }
      
      val st1 = StructType(
      StructField("ii",StringType,true) :: 
      StructField("i",StringType,true) :: 
      StructField("iii", StructType(StructField("iv", StringType, true) :: Nil), true) :: Nil)
      
      val st2 = StructType(
      StructField("i",StringType,true) :: 
      StructField("ii",StringType,true) :: 
      StructField("iii", StructType(StructField("v", StringType, true) :: Nil), true) :: Nil)
      
      isEqual(st1, st2)
      

      它也可以使用更多的爱来成为尾递归。

      【讨论】:

        猜你喜欢
        • 2019-04-09
        • 1970-01-01
        • 1970-01-01
        • 2018-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-27
        • 1970-01-01
        相关资源
        最近更新 更多