似乎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>
基本上是StructType
,我可以content comparison for that works for Seq
,但我正在考虑一种可以对嵌入式tail
进行比较的方法最有效率。
答案 0 :(得分:3)
我比较如下模式:
assert(structType1 == structType2, "not equal schemas")
即使在Spark的代码中,他们也使用'=='
比较StructTypes您可以在 org.apache.spark.sql.sources
下检出 TableScanSuite.scalaassert(expectedSchema == spark.table("tableWithSchema").schema)
我希望对您有帮助
答案 1 :(得分:1)
这可以清理,但它可以工作并处理嵌套的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)
它也可以使用更多的爱来成为尾递归。