如何比较两个共享相同内容的StructType?

问题描述 投票:0回答:3

看起来

StructType
保留了顺序,因此两个包含相同
StructType
StructField
不被认为是等价的。

例如:

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
的结果应该只有
StructType
中的一个
A
而不是两个,但是
distinct
认为这两个
StructType
是不同的,所以我最终得到了两个不同的
StructField
,名为
A
。所以我的问题是,有没有办法根据内容而不是订单来比较两个
StructType

编辑:

经过进一步调查,由于

StructType
基本上是
Seq<StructField>
,我可以对适用于Seq
的内容进行
内容比较,但我正在尝试想出一种最有效地对嵌入式
StructType
进行比较的方法.

scala apache-spark apache-spark-sql
3个回答
5
投票

这可能可以清理,但它可以工作并处理嵌套的 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)

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


4
投票

我比较模式如下:

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)

希望对你有帮助


0
投票

看看这个链接 - https://github.com/MrPowers/chispa/blob/main/chispa/schema_comparer.py 以及网站上提供的后续示例。

© www.soinside.com 2019 - 2024. All rights reserved.