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

  1. Получение всех записей List[Option[T]], имеющих значение

Самый простой способ получить все значения из списка опций — сгладить его. скажем для

val list1 = List(Some(1),None,None,Some(2))
list1.flatten 
//res1: List[Int] = List(1, 2)

Однако, если вы хотите применить определенные ограничения или преобразовать этот список, то сглаживания недостаточно, и можно использовать комбинацию flatMap и map.

list1.flatMap(_.map(_+1))
//res1: List[Int] = List(2,3)

в противном случае более чистым подходом было бы использование метода сбора

list1.collect{
  case Some(x) => x + 1
}
//res1: List[Int] = List(2,3)

2.Обобщающий список опций

Возможны два сценария суммирования списка вариантов

i) List(Some(1), ..., Some(n)) --> Some(1 + ... + n)

  • List(Some(1), ..., Some(n), None) --> None
  • List(None, ..., None) --> None

Для этого можно просто использовать функцию fold для перебора списка.

list1.fold(Option(0)){
  (rs,x) =>
    for(n <- x;
        m <- rs
    )
      yield {n+m}
}
//res2: Option[Int] = None

ii) Во втором сценарии мы хотели бы игнорировать все значения None и суммировать оставшиеся элементы списка, т.е.

List(Some(1), ..., Some(n), None) --> Some(1+...+ n)

Здесь мы можем объединить код из 1) и 2), т.е.

list1.flatten.reduceOption(_ + _)
//res3: Option[Int] = Some(3)

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

Ссылки

https://stackoverflow.com/questions/39337169/sum-a-list-of-options-in-scala