В большинстве случаев наша модель предметной области содержит необязательные поля, и в нашем приложении мы имеем дело со списком моделей предметной области для выполнения определенных операций. Однако иногда становится сложно обработать список опций, чтобы получить желаемый результат. В этой статье в основном рассматриваются два часто встречающихся состояния.
- Получение всех записей
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