Как глубоко сравнить каждый элемент с другими элементами в списке в scala (необязательные поля) - PullRequest
2 голосов
/ 24 февраля 2020

У меня есть класс дел, который представляет отчет, и отчет имеет расходы.

case class FakeExpense(amount: Option[Double], country: Option[String], currency: Option[String])
case class FakeReport(id: Int, expenses: List[FakeExpense])

, и я хочу вернуть истину / ложь, если отчет действителен или нет, и недействителен, если есть 2 расходы с точно такими же полями ... что было бы правильным для scala сделать что-то подобное?

действительный отчет:

val report = FakeReport(1, List(FakeExpense(Some(150), Some("US"), Some("USD")),FakeExpense(Some(85), Some("DE"), Some("EUR"))))

недопустимый отчет:

val report = FakeReport(2, List(FakeExpense(Some(150), Some("US"), Some("USD")),FakeExpense(Some(150), Some("US"), Some("USD"))))

Спасибо!

Ответы [ 2 ]

4 голосов
/ 24 февраля 2020

Рассмотрим List.distinct подход, подобный этому

def isValidReport(report: FakeReport): Boolean =
  report.expenses.distinct.length == report.expenses.length

Приведенное выше решение делает три прохода по списку. Применяя комментарий Луиса, мы можем сократить до двух проходов следующим образом:

def isValidReport(report: FakeReport): Boolean = {
  report.expenses.sizeIs == report.expenses.iterator.distinct.length
}

Мы сбриваем один проход, потому что distinct.length падает до одного преобразования в iterator.distinct.length. sizeIs - это потенциальная быстрая экономия, при которой нам может не потребоваться go по всему списку.

Вот однопроходное хвостово-рекурсивное решение на основе HashSet O (e C) поиск и вставка

def isValidReport(report: FakeReport): Boolean = {
  val set = mutable.HashSet[FakeExpense]()
  @tailrec def loop(l: List[FakeExpense]): Boolean = l match {
    case Nil => true
    case h :: t => if (set.add(h)) loop(t) else false
  }
  loop(report.expenses)
}

Также обратите внимание, как мы могли бы вернуться на ранней стадии с первым дубликатом.

3 голосов
/ 24 февраля 2020

Если вам нужны точно одинаковые отчеты без учета двойного сравнения с epsilon (| ab |

fakeReport.expenses.toSet.length == fakeReport.expenses.length

Он будет работать до тех пор, пока все, что внутри ваших классов вы хотите использовать с ==, правильно не реализует методы equals (примитивные типы, большинство классов по умолчанию, классы case и объекты Сделай так). То, что не реализует это правильно, это массив и, возможно, определенные классы java, и эти классы обернуты в классы AnyVal.

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