#scala
#scala
Вопрос:
У меня есть простая карта
val m = Map("a1" -> "1", "b2" -> "2", "c3" -> "3")
val someList = List("b", "d")
m.filterNot( (k,v) => someList.exist(l => k.startsWith(l)) )
Я получаю сообщение об ошибке:
error: missing parameter type
Я уверен, что я делаю здесь что-то глупое, почему это не компилируется?
Ответ №1:
filterNot
требуется case
ключевое слово и {}
при извлечении k, v
из кортежа.
обратите внимание, что exist
это не его exists
m.filterNot { case (k,v) => someList.exists(l => k.startsWith(l)) }
или
m.filterNot(pair => someList.exists(l => pair._1.startsWith(l)))
Объяснение
Поскольку вы извлекаете k, v из кортежа, используя синтаксис экстрактора, вы должны использовать case
ключевое слово и {}
Без синтаксиса экстрактора вы можете сделать
m.filterNot(pair => someList.exists(l => pair._1.startsWith(l)))
Scala REPL
scala> val m = Map("a1" -> "1", "b2" -> "2", "c3" -> "3")
m: scala.collection.immutable.Map[String,String] = Map(a1 -> 1, b2 -> 2, c3 -> 3)
scala> val someList = List("b", "d")
someList: List[String] = List(b, d)
scala> m.filterNot { case (k,v) => someList.exists(l => k.startsWith(l)) }
res15: scala.collection.immutable.Map[String,String] = Map(a1 -> 1, c3 -> 3)
Без синтаксиса экстрактора
Теперь вам не нужно использовать case
ключевое слово и {}
, поскольку мы не используем извлечение ключа и значения с использованием синтаксиса экстрактора
scala> m.filterNot(pair => someList.exists(l => pair._1.startsWith(l)))
res18: scala.collection.immutable.Map[String,String] = Map(a1 -> 1, c3 -> 3)
scala> val m = Map("a1" -> "1", "b2" -> "2", "c3" -> "3")
m: scala.collection.immutable.Map[String,String] = Map(a1 -> 1, b2 -> 2, c3 -> 3)
scala> val someList = List("b", "d")
someList: List[String] = List(b, d)
scala> m.filterNot(pair => someList.exists(l => pair._1.startsWith(l)))
res19: scala.collection.immutable.Map[String,String] = Map(a1 -> 1, c3 -> 3)
Комментарии:
1. Или просто:
(pair => someList.exists(pair._1.startsWith))
2. Хм, я этого не вижу. Все ваши примеры передают
l
параметр явно:startsWith(l)
на самом деле его можно уменьшить еще больше,m.filterNot(someList exists _._1.startsWith)
, но теперь мы рискуем скрыть код, будучи слишком милыми с синтаксисом.
Ответ №2:
Проблема заключается в следующем: filterNot
метод принимает один параметр, в то время как вы определяете список из двух параметров. Это сбивает с толку компилятор, и это сообщение является результатом.
Чтобы решить эту проблему, вы можете использовать следующий синтаксис (обратите внимание на использование сопоставления с шаблоном с case
ключевым словом):
m.filterNot { case (k,v) => someList.exist(l => k.startsWith(l)) }
Использование сопоставления с шаблоном, подобное этому, создает a PartialFunction
, который будет разлагать ключ и значение и применяться как обычная функция к вашему Map
.
Комментарии:
1. Обратите внимание, что, поскольку вы не используете значение, вы можете отказаться от значения, используя
_
подобное:m.filterNot { case (k, _) => someList.exist(l => k.startsWith(l)) }
2. В какой-то момент в будущем это раздражение будет устранено, согласно создателю языка Мартину Одерски: youtu.be/_2oGY8l67jk?t=34m50s
Ответ №3:
Использование синтаксиса для понимания, извлечения и фильтрации может быть достигнуто следующим образом,
for ( pair@(k,v) <- m; l <- someList if !k.startsWith(l)) yield pair