Scala / Java: сравнить два списка / установить и удалить сопоставленный элемент из обоих списков - PullRequest
0 голосов
/ 14 октября 2019

У меня есть два списка с двумя разными типами, но оба типа имеют одно и то же поле для идентификации / сравнения.

Мое требование: я хочу сравнить два списка на основе некоторых полей объектов, один раз найденный элемент deleteиз обоих списков / наборов. Например:

    case class Type1(name:String, surname: String, address: Int)
    case class Type2(name:String, surname: String, address: Int, dummy: String)

Таким образом, запись будет сопоставлена, если оба списка имеют одинаковые данные поля для обоих типов.

Мой список:

    val type1List = List(Type1("name1","surname1", 1),
        Type1("name2","surname2", 2),
        Type1("name3","surname3", 3)
        )

    val type2List = List(Type2("name1","surname1", 1),
        Type2("name2","surname2", 2),
        Type2("name4","surname4", 4)
        )

Сравнение type1List иtype2List, удалил соответствующую дату из обоих списков. type1List должен содержать только:

    val type1List = List(
        Type1("name3","surname3", 3)
        )

type2List должен содержать только:

    val type2List = List(
        Type2("name4","surname4", 4)
        )

Я пробовал это с циклом / взаимодействием, но это кажется слишком сложным и снижение производительности. Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 14 октября 2019

Если вы не можете настроить 2 Типы , вот прагматическое решение:

Сначала найдите «равно»

  val equals: Seq[Type1] = type1List.filter {
    case Type1(n, sn, a) =>
     type2List.exists { case Type2(n2, sn2, a2, _) =>
        n == n2 && sn == sn2 && a == a2
      }
  }

Затем отфильтруйте оба списка:

  val filteredType1List = type1List.filterNot(t1 => equals.contains(t1))
  val filteredType2List = type2List.filterNot {
    case Type2(n2, sn2, a2, _) =>
      equals.exists { case Type1(n, sn, a)=>
         n == n2 && sn == sn2 && a == a2
    }
  }
0 голосов
/ 14 октября 2019

Вот общий подход к задаче.
Идея состоит в том, чтобы найти общие элементы в обоих списках в соответствии с некоторыми пользовательскими функциями, а затем удалить их оба.

def removeCommon[A, B, K](as: List[A], bs: List[B])
                         (asKey: A => K)
                         (bsKey: B => K): (List[A], List[B]) = {
  def removeDuplicates[V](commonKeys: Set[K], map: Map[K, List[V]]): List[V] =
    map
      .iterator
      .collect {
        case (key, value) if (!commonKeys.contains(key)) =>
          value.head
      }.toList

  val asByKey = as.groupBy(asKey)
  val bsByKey = bs.groupBy(bsKey)

  val commonKeys = asByKey.keySet & bsByKey.keySet

  val uniqueAs = removeDuplicates(commonKeys, asByKey)
  val uniqueBs = removeDuplicates(commonKeys, bsByKey)

  (uniqueAs, uniqueBs)
}

Какой выможно использовать как следующее:

final case class Type1(name:String, surname: String, address: Int)
final case class Type2(name:String, surname: String, address: Int, dummy: String)

val type1List = List(
  Type1("name1","surname1", 1),
  Type1("name2","surname2", 2),
  Type1("name3","surname3", 3)
)

val type2List = List(
  Type2("name1","surname1", 1, "blah"),
  Type2("name2","surname2", 2, "blah"),
  Type2("name4","surname4", 4, "blah")
)

val (uniqueType1List, uniqueType2List) =
  removeCommon(type1List, type2List) { type1 =>
    (type1.name, type1.surname, type1.address)
  } { type2 =>
    (type2.name, type2.surname, type2.address)
  }

// uniqueType1List: List[Type1] = List(Type1("name3", "surname3", 3))
// uniqueType2List: List[Type2] = List(Type2("name4", "surname4", 4, "blah"))
0 голосов
/ 14 октября 2019

Предполагая, что вы знаете, какое поле вы хотите использовать для diff , вот схема решения.

Сначала определите суперкласс для обоих типов:

abstract class Type(val name : String) {
  def canEqual(a: Any) = a.isInstanceOf[Type]

  override def equals(obj: Any): Boolean = obj match {
    case obj : Type => obj.canEqual(this) && this.name == obj.name
    case _ => false
  }
  override def hashCode(): Int = this.name.hashCode
}

Затем определите ваши типы как подтипы вышеуказанного класса:

case class Type1(override val name: String, surname: String, address: Int) extends Type(name)
case class Type2(override val name: String, surname: String, address: Int, dummy: String) extends Type(name)

Теперь простое

type1List.diff(type2List)

приведет к:

List(Type1(name3,surname3,3))

и

type2List.diff(type1List)

даст:

List(Type2(name4,surname4,4,dum3))

Тем не менее, я был бы осторожен с такими решениями. Потому что обход equals и hashcode открывает код для всех видов ошибок. Поэтому лучше убедиться, что это ограничено областью, в которой вы работаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...