Изменить конструкцию if-else в более функциональном стиле? - PullRequest
6 голосов
/ 02 ноября 2011

возможно ли изменить эту конструкцию if-else в более функциональный стиль Scala?

def getMIMEType(document: String): String = {

  if (document.endsWith(".pdf")) {
    return "application/pdf"
  } else if (document.endsWith(".dxf")) {
    return "application/dxf"
  } else if (document.endsWith(".jpg")) {
    return "image/jpeg"
  } else return "application/octet-stream"
}

Я пытался использовать сопоставление с образцом, но это не работает. Так что мне было бы интересно найти хорошее решение.

Заранее спасибо!

Понго

Ответы [ 3 ]

35 голосов
/ 02 ноября 2011

MIME-тип отображения

Я согласен с @glowcoder. Я считаю, что по крайней мере в этом конкретном случае лучше иметь отображение MIME-Types. Вот версия Scala:

val MimeTypesMapping = Map(
  ".pdf" -> "application/pdf",
  ".dxf" -> "application/dxf",
  ".jpg" -> "image/jpeg"
)

def extension(fileName: String) = fileName substring (fileName lastIndexOf ".")

def getMIMEType(document: String) =
  MimeTypesMapping get extension(document) getOrElse "application/octet-stream"

Также, как отметил Рекс Керр, вы можете добавить значение по умолчанию непосредственно в определение отображения:

val MimeTypesMapping = Map(
  ".pdf" -> "application/pdf",
  ".dxf" -> "application/dxf",
  ".jpg" -> "image/jpeg"
) withDefaultValue "application/octet-stream" 

, а затем используйте его так: MimeTypesMapping(extension(document))

Шаблон соответствия

Если вам не нравится первое решение, тогда вы можете использовать сопоставление с шаблоном:

def getMIMEType(document: String) = extension(document) match {
  case ".pdf" => "application/pdf"
  case ".dxf" => "application/dxf"
  case ".jpg" => "image/jpeg"
  case _      => "application/octet-stream"
}

Преимущество этого решения в том, что вы можете использовать более сложную логику в таких условиях, как, например:

def getMIMEType(document: String) = extension(document) match {
  // ...
  case ".jpg" | ".jpeg" => "image/jpeg"
  // ...
}

Сравнение шаблонов с пользовательским экстрактором

Существует также другой способ использования сопоставления с образцом. Вы можете написать свой собственный экстрактор для расширения файла и затем использовать его в match:

object Extension {
  def unapply(fileName: String): Option[String] = {
    val idx = fileName lastIndexOf "."

    if (idx != -1) Some(fileName substring idx) else None
  }
}

def getMIMEType(document: String) = document match {
  case Extension(".pdf") => "application/pdf"
  case Extension(".dxf") => "application/dxf"
  case Extension(".jpg") => "image/jpeg"
  case _                 => "application/octet-stream"
}
5 голосов
/ 02 ноября 2011

Я не знаю точно, что такое встроенные в Scala структуры, но, похоже, вам нужна карта.Например, Java использует

val map = scala.collection.mutable.HashMap[String, String]()
map.put(".pdf","application/pdf");
map.put(".dxf","application/dxf");
map.put(".jpg","image/jpeg");

Затем в своей функции вы используете

def ext = getExtension(document); // assume this exists, eh?
if(map.containsKey(ext)) return map.get(ext);
return "application/octet-stream";

Обновление: похоже, Scala использует карту, которая очень похожа:

http://www.scala -lang.org / апи / гс / Скала / коллекция / изменяемые / Map.html

0 голосов
/ 03 января 2013

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

    def getMIMEType(document: String): String = {

        if (document endsWith ".pdf") {
             return "application/pdf"
        } 
        if (document endsWith ".dxf") {
             return "application/dxf"
        } 
        if (document endsWith ".jpg") {
             return "image/jpeg"
        } 
             "application/octet-stream"
    }

Я вижу здесь, что код не может удовлетворить ни одно из двух условий одновременно. Поэтому я бы предложил использовать приведенный выше код. Кроме того, если для последнего оператора возврата, т. Е. «Application / octet-stream», вы можете использовать правильное условие «if», если вы вычислите «if» для последней строки, тогда все возвраты могут быть удалены, иначе приведенный выше код хорош .

Также не нужно указывать тип возврата.

    def getMIMEType(document: String): String = {} 

можно записать как

    def getMIMEType(document: String) = {} 

проверьте, работает ли он на вас.

...