本文介绍了如何比较两个共享相同内容的StructType?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎 StructType 保留顺序,因此两个包含相同 StructField StructType 并不等效.

It seems like StructType preserves order, so two StructType containing same StructFields are not considered equivalent.

例如:

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),只是顺序不同.

returns false even though they both have StructField("i",StringType,true) and StructField("ii",StringType,true), just in different order.

我需要一个测试,可以说这两个是等效的,因为出于我的目的,这两个没有区别.

I need a test that can say that these two are equivalent because for my purpose, these two are not different.

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 不同,所以我最终得到两个名为 A 的不同 StructField .所以我的问题是,有没有一种方法可以根据其内容而不是按订单比较两个 StructType ?

The result of final_schmea should only have one StructType of A instead of two, but distinct considers these two StructType as different, so I end up getting two different StructField named A. So my question is, is there a way to compare two StructTypes based on their contents, not on orders?

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

After further investigation, since StructType is basically Seq<StructField>, I can do content comparison for that works for Seq, but I am trying to think of a way I can do comparison for embedded StructType most efficiently.

推荐答案

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

This can probably be cleaned up, but it works and handles nested 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)

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

It could also use a little more love to become tail recursive, too.

这篇关于如何比较两个共享相同内容的StructType?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-23 16:43