Параметр Scala, если существует, затем установите несколько значений val, если нет, установите те же несколько значений val в пустую строку

#scala

#scala

Вопрос:

У меня есть объект Option employee. От employee я хочу получить имя, отдел, адрес, номер, возраст или что-либо еще из него, если оно существует, но если нет, то имя, отдел и все остальное, что я хочу установить в «».

Я хотел бы просто сделать, как в Java:

 if (employee.isDefined) {
  val name = employee.get.getEmployeName
  val department = employee.get.getDepartment
  val address = employee.get.getAddress
  val number = employee.get.getNumber
  val age = employee.get.getAge
} else {
  val name, department, address, number, age = ""
}
  

но я узнал, что это так не работает. Похоже, мне понадобится другой объект employee и установите значения like, а затем получите к нему доступ позже:

 if (employee.isDefined) {
  emp.setName(employee.get.getEmployeName)
  emp.setDepartment(employee.get.getDepartment)
  ...
} else {
  emp.setName("")
  emp.setDepartment("")
  ...
}
  

Я также экспериментировал с кортежами?

 val employeeInfo = employee match {
  case Some(emp) => (employee.getEmployeName, employee.getDepartment, employee.getAddress, 
                    employee.getNumber, employee.getAge)
  case None => ("", "", "", "", "")
}
val name = employeeInfo._1
val department = employeeInfo._2
val address = employeeInfo._3
...
  

Подходят ли эти методы? Или есть какие-либо лучшие способы сделать это? Спасибо за помощь

Комментарии:

1. Итак, вы хотите перейти от Option[Employee] к Employee ? Вы можете просто сделать employee.getOrElse(Employee("","","",""))

2. Это сработало бы, но я упростил внутри объекта employee есть как бы 50 различных переменных-членов, поэтому мне пришлось бы установить для всех 50 из них пустую строку(«», «», «», «» …). Я просто хочу получить 5-6 переменных или установить их в пустую строку

3. Честно говоря, похоже, что вам нужно переосмыслить свой дизайн. Не очень хорошая идея устанавливать такие значения в пустую строку, не говоря уже о такой сложной структуре данных с 50 полями. Если вы хотите вручную выбрать эти поля, у вас нет другого выбора, кроме как сделать это вручную. Вероятно, вы могли бы определить сложную линзу, чтобы помочь вам, но она не будет короче или чище, чем сопоставление с образцом. Единственное улучшение, которое вы можете сделать здесь, — это свернуть объявления значений до val (name, department, address, number, age) = employee match {...}

4. Я пытаюсь создать API, в котором, если объект employee существует, он будет отображать правильные значения или просто пустую строку, если нет, возможно, мне следовало быть более ясным. Я мог бы просто вообще опустить эти переменные, если null. Спасибо за ваше предложение, я рассмотрю его

5. Обычной практикой является возврат 404 Not Found в этом случае. Я никогда не видел, чтобы API возвращал пустой объект, если он не может найти запрошенный ресурс

Ответ №1:

.getOrElse() это обычный способ извлечения значения из Option при указании значения по умолчанию, если опция есть None .

В вашем случае, однако, это контейнер многих значений, которые могут быть None . Для этого я бы рекомендовал .fold() .

 case class Employee(empName : String
                   ,dept    : String
                   ,addr    : String
                   ,num     : String
                   ,age     : String)

val employee: Option[Employee] =
  Some(Employee("Jo","mkt","21A","55","44"))
//or  None

val name       = employee.fold("")(_.empName)
val department = employee.fold("")(_.dept)
val address    = employee.fold("")(_.addr)
val number     = employee.fold("")(_.num)
val age        = employee.fold("")(_.age)
  

Но я должен согласиться с комментариями от @sinanspd, ваш общий дизайн в лучшем случае сомнителен.

Ответ №2:

Вот как я бы справился с этой конкретной операцией:

 val (name, department, address, number, age) =
  employee.fold(("", "", "", "", "")) { e =>
    (e.getEmployeName, e.getDepartment, e.getAddress, e.getNumber, e.getAge)
  }
  

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

 val employeeData: Option[(String, String, String, String, String)] =
  employee.map{ e =>
    (e.getEmployeName, e.getDepartment, e.getAddress, e.getNumber, e.getAge)
  }
  

Это позволяет вам определить, является ли значение, "" потому что employee было None или потому, что значение в Employee объекте было "" . И вы, вероятно, определили бы другое class для представления этого ограниченного набора данных сотрудника, чтобы сделать код более чистым и понятнее.