如何比较共享相同内容的两个结构类型?



似乎StructType保持顺序,因此包含相同StructField的两个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的结果应该只有A的一个StructType而不是两个,但distinct认为这两个StructType是不同的,所以我最终得到了两个不同的StructField命名为A.所以我的问题是,有没有办法根据它们的内容而不是订单来比较两个StructType

编辑:

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

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

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

我比较架构如下:

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

即使在Spark的代码中,他们也使用" == " 来比较StructType

。您可以在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)

我希望它有所帮助

相关内容

  • 没有找到相关文章

最新更新