如何将一个自定义对象与该序列中的另一个对象进行比较,从而从一个序列中创建两个序列?

How to create two sequence out of one comparing one custom object with another in that sequence?

case class Submission(name: String, plannedDate: Option[LocalDate], revisedDate: Option[LocalDate])

val submission_1 = Submission("Åwesh Care", Some(2020-05-11), Some(2020-06-11))
val submission_2 = Submission("robin Dore", Some(2020-05-11), Some(2020-05-30))
val submission_3 = Submission("AIMS Hospital", Some(2020-01-24), Some(2020-07-30))

val submissions = Seq(submission_1, submission_2, submission_3)

拆分 submissions 以便提交具有相同的 plannedDate and/or revisedDate 转到 sameDateGroup,其他人转到 remainder.

val (sameDateGroup, remainder) = someFunction(submissions)

示例结果如下:

sameDateGroup 应该有

Seq(Submission("Åwesh Care", Some(2020-05-11), Some(2020-06-11)),
    Submission("robin Dore", Some(2020-05-11), Some(2020-05-30)))

剩余应该有:

Seq(Submission("AIMS Hospital", Some(2020-01-24), Some(2020-07-30)))

我认为这会成功。

对不起,一些变量名不是很有意义,因为我在尝试这个时使用了不同的大小写 class。出于某种原因,我只是想过以后使用 .groupBy 。所以我真的不推荐使用这个,因为它有点难以理解,可以用 groupby

更容易解决
case class Submission(name: String, plannedDate: Option[String], revisedDate: Option[String])

val l = 
  List(
    Submission("Åwesh Care", Some("2020-05-11"), Some("2020-06-11")),
    Submission("robin Dore", Some("2020-05-11"), Some("2020-05-30")),
    Submission("AIMS Hospital", Some("2020-01-24"), Some("2020-07-30")))

val t = l
  .map((_, 1))
  .foldLeft(Map.empty[Option[String], (List[Submission], Int)])((acc, idnTuple) => idnTuple match {
    case (idn, count) => {
      acc
        .get(idn.plannedDate)
        .map { 
          case (mapIdn, mapCount) => acc + (idn.plannedDate -> (idn :: mapIdn, mapCount + count))
        }.getOrElse(acc + (idn.plannedDate -> (List(idn), count)))
    }})
  .values
  .partition(_._2 > 1)

val r = (t._1.map(_._1).flatten, t._2.map(_._1).flatten)

println(r)

它基本上遵循 map-reduce wordcount 模式。

如果有人看到这个,并且知道如何更容易地解构元组,请在评论中告诉我。

所以,如果我理解这里的逻辑,提交 A 与提交 B 共享一个日期(并且两者都会进入 sameDateGrooup) IFF:

   subA.plannedDate == subB.plannedDate
OR subA.plannedDate == subB.revisedDate
OR subA.revisedDate == subB.plannedDate
OR subA.revisedDate == subB.revisedDate

同样,相反,提交 C 属于 remainder 类别 IFF:

    subC.plannedDate // is unique among all planned dates
AND subC.plannedDate // does not exist among all revised dates
AND subC.revisedDate // is unique among all revised dates
AND subC.revisedDate // does not exist among all planned dates

考虑到所有这些,我认为这符合您的描述。

import java.time.LocalDate

case class Submission(name        : String
                     ,plannedDate : Option[LocalDate]
                     ,revisedDate : Option[LocalDate])

val submission_1 = Submission("Åwesh Care"
                             ,Some(LocalDate.parse("2020-05-11"))
                             ,Some(LocalDate.parse("2020-06-11")))
val submission_2 = Submission("robin Dore"
                             ,Some(LocalDate.parse("2020-05-11"))
                             ,Some(LocalDate.parse("2020-05-30")))
val submission_3 = Submission("AIMS Hospital"
                             ,Some(LocalDate.parse("2020-01-24"))
                             ,Some(LocalDate.parse("2020-07-30")))

val submissions = Seq(submission_1, submission_2, submission_3)

val pDates = submissions.groupBy(_.plannedDate)
val rDates = submissions.groupBy(_.revisedDate)
val (sameDateGroup, remainder) = submissions.partition(sub =>
          pDates(sub.plannedDate).lengthIs > 1 ||
          rDates(sub.revisedDate).lengthIs > 1 ||
          pDates.keySet(sub.revisedDate) ||
          rDates.keySet(sub.plannedDate))

一个简单的方法是计算列表中每个提交的匹配提交数,并用它来划分列表:

def matching(s1: Submission, s2: Submission) =
  s1.plannedDate == s2.plannedDate || s1.revisedDate == s2.revisedDate

val (sameDateGroup, remainder) =
  submissions.partition { s1 =>
    submissions.count(s2 => matching(s1, s2)) > 1
  }

matching 函数可以包含任何需要的特定测试。

这是O(n^2),因此对于很长的列表需要更复杂的算法。