Scala Map получить значение по ключу с учетом регистра без учета регистра - PullRequest
2 голосов
/ 15 мая 2019

У меня есть карта Map [String, Info], она содержит ключи, которые могут быть как в верхнем, так и в нижнем регистре, например:

person1: PersonInfo1
person2: PersonInfo2
PERSON1: PersonInfo1

я хочу получить значение для ключа 'person1', если ничего не найдено, я попробую с ключом 'PERSON1', я попробовал этот код:

val info = map.get(key) match {
  case Some(personInfo) => personInfo
  case None =>
    map.get(key.toUpperCase()) match {
      case Some(personInfo) => personInfo
      case None             => None
    }
}

но эта возвращаемая информация как тип продукта с Serializable, как я могу получить информацию, возвращаемую как тип PersonInfo? Есть ли способ в Scala, который позволяет мне получить значение из карты по ключу и игнорировать случаи ключа?

Ответы [ 3 ]

4 голосов
/ 15 мая 2019

Причина, по которой вы получаете Product with Serializable, заключается в том, что ваш код пытается вернуть либо String (если ключ в порядке), либо Option (т.е. None, если ключ не найден).Эти два типа не совместимы.Вы должны решить, хотите ли вы String (возможно, пустую строку, если ключ не найден) или Option (т.е. Some[String] или None).

Проверьте, работает ли этодля тебя.Возвращает Option[String].

map.get(key).fold(pm.get(key.toUpperCase))(Some(_))

1-й get() возвращает Option.fold()() разворачивает Option и либо пытается 2-й get() со значением key в верхнем регистре, либо, если 1-й get вернул значение, значение повторно упаковывается в Option, так чтотипы совпадают.

Если, с другой стороны, вы хотите вернуть String, вы можете сделать это.

map.getOrElse(key, pm.getOrElse(key.toUpperCase, ""))
4 голосов
/ 15 мая 2019

Вы можете получить цепочку с orElse. Я бы создал метод расширения для этого:

implicit class CaseInsensitiveGetMap[V] (m: Map[String,V]) {
   def iget (key: String): Option[V] = m.get(key)
      .orElse(m.get(key.toUpperCase())) //you can add more orElse in chain
}

Тогда вы можете просто использовать его как:

map.iget("person2")
4 голосов
/ 15 мая 2019

Существуют компараторы для отсортированных карт, которые позволяют незаметно получать регистр карт.Пример: https://scastie.scala -lang.org / PfHTh16CROag7PNrknx1sQ

val map = scala.collection.immutable.SortedMap("key1" -> 45, "Key2" -> 43, "KEY3" -> 42)(scala.math.Ordering.comparatorToOrdering(String.CASE_INSENSITIVE_ORDER))
map.get("key1") // Some(45)
map.get("key2") // Some(43)
map.get("key3") // Some(42)
map.get("key4") // None

Ваша реальная проблема может быть исправлена, если вы вернете Опции во всех случаях, например:

      val info = map.get(key) match {
        case somePi@Some(personInfo) => somePi
        case None => map.get(key.toUpperCase()) match {
          case Some(personInfo) => Some(personInfo)
          case None => None
        }
      }

Обратите внимание на somePi@ => somePi части для ссылки на выражение или Some(personInfo).

Вероятно, стоит объяснить почему вы получили это сообщение об ошибке.Я предполагаю, что personInfo - это case class, который реализует Product и Serializable, точно так же как None.Общий тип для них Product with Serializable.

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