Самый тривиальный поиск на картах, похоже, возвращает параметр [Что-то]

#scala #maps

#scala #Карты

Вопрос:

Я знаю, что результаты maps разделяются на

  • Нет
  • Некоторые

Однако я хотел бы получить обратно (при использовании поиска) только фактический объект, на который указывают. Позвольте мне немного прояснить:

У меня есть карта abc

 val abc = Map( 1 -> List("a","b"), 2 -> List("z","y") )
  

И я хочу как-то вернуться

 List("a","b")
  

Я пытался:

 abc(1) // return a List
  

Я попытался сопоставить шаблон:

 abc get 1 match {
  case Some(x) => x
}   
  

Но совпадение с шаблоном возвращает объект

Я пытался добиться этого, используя для :

 (for((int, string) <- abc; if(int == 1)) yield string)
  

Но он возвращает неизменяемый объект итератора.

Я знаю, что этот ответ очень простой, но я не могу разобраться в этом, и я не могу найти в Интернете ничего, что связано с этим

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

1. Что, черт возьми, вы делаете, чтобы получить Option ? abc(1) = List("a","b") .

2. abc(1) определенно не является Option (вот почему это такая ужасная идея).

3. Мой плохой. abc (1) для меня есть res2: Object . То, что я хочу, это List

4. Похоже, вы используете Java Map, выполняете какие-то преобразования или, может быть, вы объявили свою карту где-то как Map[Int, Object] ? Проверьте свой импорт или добавьте к карте префикс с пакетом, чтобы проверить: scala.collection.immutable.Map .

5. @AlekseyIzmailov проверить комментарий к ответу

Ответ №1:

Обновил его:

 $ scala
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val abc = Map( 1 -> List("a","b"), 2 -> List("z","y") )
abc: scala.collection.immutable.Map[Int,List[String]] = Map(1 -> List(a, b), 2 -> List(z, y))
  

Я вижу здесь разницу: у вас есть опция. Но я вернул список. Как вы можете видеть, я на Scala 2.10.4

 scala> abc(1)
res0: List[String] = List(a, b)

scala> abc get 1 match { case Some(x) => x }
<console>:9: warning: match may not be exhaustive.
It would fail on the following input: None
              abc get 1 match { case Some(x) => x }
                  ^
res1: List[String] = List(a, b)
  

Опять же, я вижу что-то отличное от того, что вы видите. Я вернул список, а не объект.

 scala> (for((int, string) <- abc; if(int == 1)) yield string)
res2: scala.collection.immutable.Iterable[List[String]] = List(List(a, b))
  

Да, я вернул неизменяемый итератор[Список [Строка]] . Если вам просто нужен тип List [String], вы также можете сделать это:

 scala> res2.toList.flatMap(identity)
res3: List[String] = List(a, b)
  

В основном identity функция сводится к этому:

 scala> res2.toList.flatMap(i => i)
res4: List[String] = List(a, b)
  

Или вы даже можете сделать это:

 scala> res2.toList.flatten
res5: List[String] = List(a, b)
  

Некоторые моменты: вам следует избегать применения к карте и делать get , потому что вы увидите это:

 scala> abc(3)
java.util.NoSuchElementException: key not found: 3

scala> abc.get(3)
res7: Option[List[String]] = None
  

Я предпочитаю что-то вроде:

 scala> abc.get(1).getOrElse(List.empty[String])
res10: List[String] = List(a, b)
  

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

1. Похоже, что я добавил значение по умолчанию, используя значение withDefaultValue, к моей карте, и это привело к тому, что скобки вернули объект. Я приму этот ответ, потому что он настолько подробный, однако вы можете добавить, что добавление значения по умолчанию приведет к получению значений, отличных от ожидаемых

Ответ №2:

Вероятно, вы добавили значение по умолчанию на карту, которая имеет объект только как общий супертип со списком.

Метод withDefaultValue использует нижнюю границу типа для типа значений на карте. Поэтому, когда вы это сделаете Map( 1 -> List("a","b"), 2 -> List("z","y") ) .withDefaultValue("x") , результатом будет Map[Int, Object]