Как сравнить объекты в 2 векторах в scala - PullRequest
0 голосов
/ 09 мая 2020

У меня есть 2 вектора, определенные с помощью следующих данных: vector1 и vector2 определены как Vector [Person], где у человека могут быть записи как ученика, так и учителя.

val v1 = """[
   {
      "category":"common",
      "type":"student",
      "roles":[
         {
            "name":"A",
            "type":"Type1"
         },
         {
            "name":"B",
            "type":"Type1"
         },
         {
            "name":"C",
            "type":"Type2"
         },
         {
            "name":"D",
            "type":"Type2"
         }
      ]
   }
]"""

val v2 = """[
   {
      "category":"common",
      "type":"student",
      "roles":[
         {
            "name":"A",
            "type":"Type1"
         },
         {
            "name":"B",
            "type":"Type1"
         },
         {
            "name":"C",
            "type":"Type2"
         },
         {
            "name":"D",
            "type":"Type2"
         }
      ]
   },
   {
      "type":"Teacher",
      "roles":[
         {
            "name":"AB",
            "type":"Type1"
         },
         {
            "name":"BC",
            "type":"Type1"
         },
         {
            "name":"CD",
            "type":"Type2"
         },
         {
            "name":"DE",
            "type":"Type2"
         }
      ]
   }
]"""

Мне нужно сравнить оба этих вектора в зависимости от атрибута, т.е. типа. Это значение может быть учеником или учителем. Если тип такой же, мне следует проверить роли.

Я пробовал использовать zipwithindex / index, но похоже, что сравниваются только элементы в этом индексе. Есть ли способ сравнения на основе типа каждого элемента в векторе. Я хочу объявить оба вектора равными, если типы и роли одинаковы.

Примечание: приведенные выше примеры являются jsons, и мы считываем их в наш класс case

  case class Person(
      category: String,
      name: Option[String],
      `type`: Option[String],
      roles: List[Role]
  )

  case class Role(name: String, `type`: String)

и vector1 / vector2 читаются как Vector[Person]

1 Ответ

1 голос
/ 10 мая 2020

Когда вы создаете класс case, у него есть несколько реализованных методов, один из которых - метод equals. Это означает, что экземпляры класса case сравниваются не по ссылке, а по структуре (метод equals просто сравнивает все атрибуты). Если вы хотите сравнить только по некоторым атрибутам, игнорируя другие, вы можете попытаться переопределить метод 'equals' (вы можете использовать простой оператор == для сравнения), НО я не рекомендую это делать. Это может сбить с толку ваш код, поскольку функция «равно» не будет работать должным образом.

Для этой цели я рекомендую написать простую функцию сравнения. Если векторы имеют разные размеры, они не могут быть равными. В противном случае вам нужно, чтобы атрибуты «тип» и «роли» совпадали. Role - это класс case, и его метод equal работает именно так, как нам нужно, поэтому оператор == работает нормально.

def personVectorsEqual(vec1 : Vector[Person], vec2 : Vector[Person]): Boolean ={
      if(vec1.size != vec2.size)
        false
      else (vec1, vec2).zipped.forall((p1, p2) => p1.`type` == p2.`type` && p1.roles == p2.roles)
}

Zipped-метод создает последовательность кортежей объектов, которые находятся в соответствующих индексах. Нам нужно сравнить объекты в кортежах. Поскольку заархивированный метод отбрасывает последние элементы более длинной последовательности (когда их размеры не равны), нам нужно явно запрашивать размеры векторов.

Примечания: просто будьте осторожны, вы действительно хотите сравнивать объекты по атрибут Option? А если их всего два типа («ученик» и «Учитель»), было бы яснее не использовать для них String. Может быть, попробуйте взглянуть на enum или запечатанные черты / классы. Кроме того, один из ваших json человек не попадает в обязательную «категорию».

...